[英]Trivial order by double type: performance crash
特点:
PostgeSQL 9.1,PostGIS 2.0。
1.查询:
SELECT ST_AsText(geo_point)
FROM lightnings
ORDER BY stroke_when DESC, stroke_when_second DESC
LIMIT 1
总运行时间: 31100.911毫秒 !
EXPLAIN(分析,VERBOSE关闭,成本开启,BUFFERS开启):
Limit (cost=169529.67..169529.67 rows=1 width=144) (actual time=31100.869..31100.869 rows=1 loops=1)
Buffers: shared hit=3343 read=120342
-> Sort (cost=169529.67..176079.48 rows=2619924 width=144) (actual time=31100.865..31100.865 rows=1 loops=1)
Sort Key: stroke_when, stroke_when_second
Sort Method: top-N heapsort Memory: 17kB
Buffers: shared hit=3343 read=120342
-> Seq Scan on lightnings (cost=0.00..156430.05 rows=2619924 width=144) (actual time=1.589..29983.410 rows=2619924 loops=1)
Buffers: shared hit=3339 read=120342
2.选择另一个字段:
SELECT id
FROM lightnings
ORDER BY stroke_when DESC, stroke_when_second DESC
LIMIT 1
总运行时间: 2144.057毫秒 。
EXPLAIN(分析,VERBOSE关闭,成本开启,BUFFERS开启):
Limit (cost=162979.86..162979.86 rows=1 width=24) (actual time=2144.013..2144.014 rows=1 loops=1)
Buffers: shared hit=3513 read=120172
-> Sort (cost=162979.86..169529.67 rows=2619924 width=24) (actual time=2144.011..2144.011 rows=1 loops=1)
Sort Key: stroke_when, stroke_when_second
Sort Method: top-N heapsort Memory: 17kB
Buffers: shared hit=3513 read=120172
-> Seq Scan on lightnings (cost=0.00..149880.24 rows=2619924 width=24) (actual time=0.056..1464.904 rows=2619924 loops=1)
Buffers: shared hit=3509 read=120172
3.正确优化:
SELECT id
FROM lightnings
ORDER BY stroke_when DESC
LIMIT 1
总运行时间: 0.044毫秒
EXPLAIN(分析,VERBOSE关闭,成本开启,BUFFERS开启):
Limit (cost=0.00..3.52 rows=1 width=16) (actual time=0.020..0.020 rows=1 loops=1)
Buffers: shared hit=5
-> Index Scan Backward using lightnings_idx on lightnings (cost=0.00..9233232.80 rows=2619924 width=16) (actual time=0.018..0.018 rows=1 loops=1)
Buffers: shared hit=5
正如您所看到的,当SQL优化器使用索引时,查询是非常原始的,但有两个不同且非常不同的冲突:
当然,上面是一个简化的查询,从更复杂的结构中提取。 通常我按日期范围选择行,应用复杂的过滤器。
PostgreSQL无法使用您的索引以前两个查询的所需顺序生成值。 当两个或多个行具有相同的store_when
相同时,它们以任意顺序从索引扫描返回。 要确定行的正确顺序,需要进行二次排序。 因为PostgreSQL执行程序没有执行该次要排序的工具,所以它又回退到完全排序方法。
如果您经常需要使用该顺序查询表,则将当前索引替换为包含两个列的复合索引。
您可以将当前查询转换为仅在store_when
的最大值上显式指定辅助排序的store_when
:
SELECT ST_AsText(geo_point) FROM lightnings
WHERE store_when = (SELECT max(store_when) FROM lightnings)
ORDER BY stroke_when_second DESC LIMIT 1
第一步可能是:在{stroke_when,stroke_when_second}上创建一个复合索引
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.