キャラクター:
- idBIGINT _
- geo_point POINT(PostGIS)
- stroke_when TIMESTAMPTZ(インデックス付き!)
- stroke_when_second倍精度
PostgeSQL 9.1、PostGIS2.0。
1.クエリ:
SELECT ST_AsText(geo_point)
FROM lightnings
ORDER BY stroke_when DESC, stroke_when_second DESC
LIMIT 1
合計実行時間:31100.911ミリ秒!
EXPLAIN(ANALYZEオン、VERBOSEオフ、COSTSオン、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(ANALYZEオン、VERBOSEオフ、COSTSオン、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(ANALYZEオン、VERBOSEオフ、COSTSオン、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オプティマイザーがインデックスを使用する場合、クエリは非常に原始的ですが、2つの悪い衝突と非常に異なる衝突があります。
- オプティマイザーがインデックスを使用しない場合でも、idの代わりにAs_Text(geo_point)を使用すると、非常に時間がかかるのはなぜですか?結果は1行だけです!
- インデックス付けされていないフィールドがORDERBYに表示されている場合、1次インデックスを使用することはできません。実際には、DBには毎秒数行しか表示されないことに注意してください。
もちろん、上記は、より複雑な構造から抽出された単純化されたクエリです。通常、複雑なフィルターを適用して、日付範囲で行を選択します。