2017-02-14 9 views
0

column_Xに基づいて、別のテーブル(500K行以上のtable_B)に対応する行がない1つのテーブル(table_Aはかなり小さい< 10K行)の行を選択する必要があります(table_Bはインデックスbtreeをonその列)。私は次のクエリを使用する場合 は: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結果の行)について600msの中で実行されます。それは同じ168行を取得するために約8分かかり

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 

: の場合は、他の一方で、私は別のクエリを試してみてください。 column_Xはbigint型であり、キャストは違いがないようです(2番目のクエリではインデックスは使用されません)。

+1

「EXPLAIN ANALYZE」の結果を共有してください - 共有するには、Web https://explain.depesz.com/をご覧ください。 –

+0

注:副問い合わせで 'where column_X not null 'は必要ありません。 – wildplasser

+0

@wildplasser 'column_X'がヌル可能な場合、*は本当に必要です。それがなければ、列に実際にNULL値が含まれていると、 'NOT IN'式(および任意の' IN'式)は 'NULL'(これはANSI SQL標準で必要です)になります。 PostgreSQLがそのクエリを反結合にしないのは、まさにその理由です。 – pozs

答えて

1

NOT INサブセレクトは他のサブセレクトよりもはるかに悪化しています。間違った意味合いがあるため、PostgreSQLはantijoinを使用できません。可能であれば、このパターンを使用しないでください。代わりにNOT EXISTS、または外部結合を使用してください。

関連する問題