0

3つのテーブルがあります。

1 番目に 10,000 行、2 番目に 80,000 行、3 番目に 400 行。

コードはうまく機能していましたが、最近パフォーマンスの問題が発生しました。

EXPLAIN ANALYZE SELECT "users_users"."id", "users_users"."email" 
FROM "users_users" WHERE (NOT ("users_users"."email" IN 
     (SELECT U0."email" FROM "users_blacklist" U0)) 
     AND NOT ("users_users"."id" IN (SELECT U0."user_id" 
FROM "games_user2game" U0))) ORDER BY "users_users"."id" DESC;
                                                                       QUERY PLAN                                                                        
---------------------------------------------------------------------------------------------------------------------------------------------------------
 Index Scan Backward using users_user_pkey on users_users  (cost=9.25..12534132.45 rows=2558 width=26) (actual time=46.101..77158.318 rows=2510 loops=1)
   Filter: ((NOT (hashed SubPlan 1)) AND (NOT (SubPlan 2)))
   Rows Removed by Filter: 7723
   SubPlan 1
     ->  Seq Scan on users_blacklist u0  (cost=0.00..8.20 rows=420 width=22) (actual time=0.032..0.318 rows=420 loops=1)
   SubPlan 2
     ->  Materialize  (cost=0.00..2256.20 rows=77213 width=4) (actual time=0.003..4.042 rows=35774 loops=9946)
           ->  Seq Scan on games_user2game u0  (cost=0.00..1568.13 rows=77213 width=4) (actual time=0.011..17.159 rows=77213 loops=1)
 Total runtime: 77159.689 ms
(9 rows)

主な質問: 100,000 行未満の 2 つのテーブルを結合する際にパフォーマンスの問題が発生しても問題ありませんか?

どこを掘る?クエリを変更するか、データベース設定を掘り下げる必要がありますか?

UPDの一時的な解決策は、コードでサブクエリをプリフェッチすることでサブクエリを取り除くことです。

4

2 に答える 2

1

@Scotchが良い効果を示唆しているように、SQL Serverで同様の問題に遭遇し、存在するクエリを書き直しました。

SELECT 
    "users_users"."id", 
    "users_users"."email" 
FROM "users_users" 
WHERE 
NOT EXISTS 
(
    SELECT NULL FROM "users_blacklist" WHERE "users_blacklist"."email" = "users_users"."email"
)
AND NOT EXISTS
(
    SELECT NULL FROM "games_user2game" WHERE "games_user2game"."user_id" = "users_users"."user_id"
)
ORDER BY "users_users"."id" DESC;

このクエリは、ブラックリストに登録されておらず、ゲームに参加していないすべてのユーザーを取得します。postgres がクエリをどのように計画するかによっては、外部結合オプションよりも高速になる場合があります。

于 2013-06-24T22:22:09.793 に答える
1

SQL の postgres ダイアレットはわかりませんが、外部結合を試してみる価値はあるかもしれません。他の多くの dbm では、副選択よりも優れたパフォーマンスを提供できます。

の線に沿った何か

SELECT "users_users"."id", "users_users"."email"
FROM "users_users" us left join  "users_blacklist" uo on uo.email = us.email
                      left join "games_user2game" ug on us.id = ug.user_id
where uo.email is null
AND   ug.id is null

元のクエリと同じことをしていると思いますが、確認するためにテストする必要があります。

于 2013-06-24T22:08:27.503 に答える