2017-02-14 99 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或外连接。