2017-02-14 97 views
0

我必須根據column_X(table_B有一個索引,btree,在一個表(table_A相當小的< 10K行)在另一個表(table_B over 500K rows)中沒有對應的行該欄)。 如果我使用以下查詢:postgresql查詢計劃奇怪的行爲

select a.column1, 
    a.column2, 
    a.column3, 
    a.column_X, 
    b.column_X 
from table_A a 
left outer join table_B b on a.column_X = b.column_X 
where a.column_X <> 0 
    and b.column_X is null 

查詢(168場所得的行)的約600毫秒被執行。 如果,另一方面,我嘗試不同的查詢:

select column1, 
    column2, 
    column3, 
    column_X 
from table_A 
where column_X not in (
     select column_X 
     from table_B 
     where column_X is not null 
     ) 
    and column_X <> 0 

大約需要8分鐘檢索相同的168行。 column_X是bigint類型,並且轉換似乎沒有區別(在第二個查詢中,索引從不使用)。 有什麼想法?

+1

請分享'EXPLAIN ANALYSE'結果 - 請參閱網站https://explain.depesz.com/以供分享。 –

+0

注意:子查詢中的where column_X不爲空是不需要的。 – wildplasser

+0

@wildplasser如果'column_X'是可爲空的,那麼它真的很需要。沒有它,如果該列實際上包含NULL值,則NOT IN表達式(和任何IN表達式)將導致NULL(這是ANSI SQL標準所要求的)。這就是爲什麼PostgreSQL不會將該查詢轉換爲反連接的原因。 – pozs

回答

1

NOT IN子選擇比其他任何優化都差得多。由於PostgreSQL不同的語義不能使用反連接。如果可以的話,不要使用這種模式。改爲使用NOT EXISTS或外連接。