1

postgres で特定の SQL クエリの実行が遅い理由を突き止めようとしています。あまり説明しませんが、クエリの EXPLAIN ANALYZE を次に示します。

explain analyze SELECT "addressbooks_address"."id", "addressbooks_address"."name" FROM "addressbooks_recipientaddress" INNER JOIN"addressbooks_address" ON ("addressbooks_recipientaddress"."address_ptr_id" = "addressbooks_address"."id") ORDER BY "addressbooks_recipientaddress"."address_ptr_id" ASC LIMIT 1000 OFFSET 378000;

QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=40139.55..40245.42 rows=1000 width=21) (actual time=720.444..721.958 rows=1000 loops=1)
   ->  Merge Join  (cost=121.88..67152.43 rows=633159 width=21) (actual time=0.028..698.069 rows=379000 loops=1)
     Merge Cond: (addressbooks_recipientaddress.address_ptr_id = addressbooks_address.id)
     ->  Index Scan using addressbooks_recipientaddress_pkey on addressbooks_recipientaddress  (cost=0.00..19258.72 rows=633159 width=4) (actual time=0.012..189.480 rows=379000 loops=1)
     ->  Index Scan using addressbooks_address_pkey on addressbooks_address  (cost=0.00..38291.65 rows=675743 width=17) (actual time=0.011..227.094 rows=388264 loops=1)
Total runtime: 722.092 ms

クエリは django によって生成されますが、ここに投稿する前に少し簡略化しました。しかし、問題はまだ残っています。説明で示されているように、addressbooks_address.id と addressbooks_recipientaddress.address_ptr_id の両方のインデックスがあります。

何か案は?

4

1 に答える 1

2

リミット 1000 オフセット 378000

あなたがやっていることは速く見えます。かなり大きな結合を生成し、その大部分を破棄しています。

を使用する代わりに、OFFSET可能であれば、関心のある行の主キーでページネーションを行ってみてください。addressbooks_address.idおよび のキーが前の結果の最後のタプルからのものであることを思い出し、addressbooks_recipientaddress次のような WHERE 句を使用します。

WHERE "addressbooks_recipientaddress"."id" > $1
  AND "addressbooks_address"."id" > $2

の代わりにOFFSET。そうすれば、結果を生成するために時間を無駄にする代わりに、インデックス スキャンをそれらのレコードにスキップすることができます。

あなたのフレームワークがそれを行うことができないなら、まあ、それが私がクエリジェネレータフレームワークを好まない理由です.

于 2013-09-06T07:06:45.687 に答える