2017-02-14 5 views
0

column_X를 기준으로 다른 테이블 (500KB 이상의 table_B)에 해당 행이없는 하나의 테이블 (table_A 상당히 작은 < 10K 행)을 선택해야합니다 (table_B에는 인덱스 btree가 on 그 열). 나는 다음과 같은 쿼리를 사용하는 경우 : 쿼리 (168 개 결과 행이) 약 600ms의에서 실행됩니다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 개 행을 검색하는 데 약 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 유형이고 casting은 아무런 차이가없는 것 같습니다 (두 번째 쿼리에서는 인덱스가 사용되지 않습니다). 아이디어가 있으십니까?

+1

공유하려면'EXPLAIN ANALYZE' 결과를 공유하십시오 - 웹 https://explain.depesz.com/을 참조하십시오. –

+0

참고 : 하위 쿼리에서'where column_X not null '은 필요하지 않습니다. – wildplasser

+0

@wildplasser'column_X'가 nullable이면, 그것은 * 정말로 필요합니다. 이를 사용하지 않으면 컬럼에 실제로 NULL 값이 포함되어 있으면 'NOT IN'표현식 (및 모든 IN 표현식)이 NULL이됩니다 (이는 ANSI SQL 표준에서 필요합니다). 이것이 바로 PostgreSQL이이 쿼리를 anti-join으로 바꾸지 않는 이유입니다. – pozs

답변

1

NOT IN subselect는 다른 어떤 것보다 훨씬 좋지 않습니다. 다른 의미 론적 이유 PostgreSQL은 antijoin을 사용할 수 없습니다. 가능한 경우이 패턴을 사용하지 마십시오. 대신 NOT EXISTS을 사용하거나 외부 조인을 사용하십시오.