すべてのインデックスが設定されているにもかかわらず、クエリの実行が非常に遅くなります。
SELECT * FROM "entry"
INNER JOIN "entrytag" ON ("entry"."id" = "entrytag"."entry_id")
WHERE "entrytag"."tag_id" = 323456
ORDER BY "entry"."date"
DESC LIMIT 10'
説明でループが多すぎますが、なぜですか?これを修正する方法?
Limit (cost=1241.85..1241.87 rows=10 width=666) (actual time=23576.449..23576.454 rows=10 loops=1)
-> Sort (cost=1241.85..1242.10 rows=99 width=666) (actual time=23576.446..23576.447 rows=10 loops=1)
Sort Key: entry.date DESC
Sort Method: top-N heapsort Memory: 31kB
-> Nested Loop (cost=0.87..1239.71 rows=99 width=666) (actual time=0.168..22494.187 rows=989105 loops=1)
-> Index Scan using entrytag_tag_id_row_idx on entrytag (cost=0.44..402.17 rows=99 width=4)
(actual time=0.093..535.664 **rows=989105** loops=1)
Index Cond: (tag_id = 323456)
-> Index Scan using entry_pkey on entry (cost=0.43..8.45 rows=1 width=666)
l time=0.020..0.021 rows=1 **loops=989105**)
Index Cond: (id = entrytag.entry_id)
Planning time: 0.829 ms
Execution time: 23576.504 ms
テーブルentry
にあるインデックス:
('id', 'date', ...other irrelevant cols)
('date', ...other irrelevant cols)
関連付けテーブルentrytag
:
(tag_id, entry_id)
(tag_id, row) -- this index is used according to the explain
PostgreSQL v 9.5。多くの行があり、dbは非常に大きいです。他のタグに対する同じクエリ(同じ数のエントリを持つ)は、ほんの数秒しかかかりません。そのような巨大な行とループのカウントはありません。
問題はここにあります
Index Scan using entrytag_tag_id_row_idx on entrytag
(cost=0.44..402.17 rows=99 width=4)
(actual time=0.093..535.664 rows=989105 loops=1)
あなたの統計は
WHERE "entrytag"."tag_id" = 323456
あなたのプランナーははるかに少ないと考えていますtag_id=323456
あります。 ANALYZE entrytag;
、そして再試行します。またはupping統計。
ALTER TABLE entrytag
ALTER COLUMN tag_id
SET STATISTICS 1000;
次に、ANALYZE entrytag;
と再試行します。悪い統計の典型的なケースのように聞こえます。
スキーマを改善したり、非正規化したりできます。 100万行を結合、選択、および注文しています。それはすぐにはいきません。