[英]Using LEFT JOIN instead of NOT IN in PostgreSQL
我正在調試 django-reversion(django 庫)中可能存在的性能錯誤。 我遇到的問題是,每次運行 django-reversion 的createinitialrevisions
,我的數據庫都會花費大量時間來處理正在發生的事情。
我在 RDS 中啟用了 Performance Insights,我看到正在殺死我的數據庫的查詢如下所示:
SELECT "table_a"."id"
FROM "table_a"
WHERE NOT (CAST("table_a"."id" as text) IN (
SELECT U0."object_id"
FROM "reversion_version" U0
WHERE (U0."content_type_id" = 49 AND U0."db" = 'default')
))
如果我正確理解我在這里讀到的內容https://explainextended.com/2009/09/16/not-in-vs-not-exists-vs-left-join-is-null-postgresql/事實證明 PostgreSQL 是不能以與LEFT JOIN
相同的方式優化NOT IN
。 這就是為什么我決定重寫這個查詢並查看它是否需要相同的時間來運行。
這是重寫后的結果:
SELECT "table_a"."id"
FROM "table_a"
LEFT JOIN
"reversion_version" U0
ON U0."object_id" = "table_a"."id"::text
WHERE U0."object_id" IS NULL AND U0."content_type_id" = 49 AND U0."db" = 'default'
我一定是做錯了什么,因為我得到了不同的結果。 我的查詢(重寫的查詢)根本沒有返回任何內容。
我錯過了什么?
正確重寫的查詢需要前一個子查詢的WHERE
條件作為LEFT JOIN
連接條件,例如:
SELECT table_a.id
FROM table_a
LEFT JOIN reversion_version U0 ON U0.object_id = table_a.id::text
AND U0.content_type_id = 49
AND U0.db = 'default'
WHERE U0.object_id IS NULL;
你嘗試的方法是邏輯上的矛盾:它會要求行的table_a
與不匹配的行reversion_version
,然后在不存在的行強加附加條件。 那永遠不會返回任何行。
它必須是相反的:在table_a
找到滿足上述條件的reversion_version
中沒有匹配行的行。 因此,將這些條件從WHERE
子句移動到LEFT JOIN
的連接子句。 細微但根本的區別。
看:
關於性能可能還有更多要說的,但並非沒有設置的必要細節......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.