2010-06-08 6 views
3

이 질문은 아마도 이전에 물어 왔지만 나는 검색 할 수 없습니다.PostgreSQL의 IN 문 성능 (일반적으로)

SELECT * FROM TABLE1 WHERE id IN SUBQUERY_ON_TABLE2; 

는 TABLE1과 TABLE2 성장의 행 수로 내려 가서하고 ID가 있습니다 :

내가 이와 같은 쿼리의 성능을 기대해야하는지, 내가 TABLE1과 TABLE2했습니다 말할 수 있습니다 TABLE1의 기본 키.

예, IN을 사용하는 것이 n00b 실수라는 것을 알고 있지만 TABLE2는 다른 여러 테이블에 일반적인 관계 (django 일반 관계)를 가지고있어서 데이터를 필터링하는 다른 방법을 생각할 수 없습니다. TABLE1과 TABLE2의 어떤 (대략적인) 행이 내가이 때문에 성능 문제를 알아야 할 것으로 예상해야합니까? 행의 수에 따라 성능이 선형, 기하 급수적으로 저하됩니까?

답변

8

하위 쿼리에서 반환하는 레코드 수가 적고 기본 쿼리에서 반환되는 결과 행의 수가 적은 경우에는 각각에 대해 빠른 인덱스 조회 만 수행됩니다. 리턴 된 데이터의 백분율이 증가함에 따라 결과적으로 두 테이블 모두 인덱스 된 테이블 대신 순차 스캔을 사용하여 한 테이블에서 전체 테이블을 함께 모으기보다는 테이블을 가져옵니다. 선형 또는 기하 급수적 인 성능의 단순한 저하는 아닙니다. 계획 변경의 유형에 따라 중대한 불연속성이 있습니다. 그리고 행의 수는 테이블의 크기에 따라 다르므로 거기에 대한 유용한 규칙도 없습니다. 아래에서 수행하는 것처럼 시뮬레이션을 작성하고 자신의 데이터 세트에서 어떤 일이 발생하는지보고 곡선이 어떻게 생겼는지 확인해야합니다.

다음은 Dell Store 2 데이터베이스와 함께로드 된 PostgreSQL 9.0 데이터베이스를 사용하는 방법의 예입니다. 하위 쿼리에 의해 반환되는 행이 1000 개가되면 기본 테이블의 전체 테이블 검색이 수행됩니다. 그리고 하위 쿼리가 10,000 개의 레코드를 고려하면 전체 테이블 스캔으로 바뀝니다. 이들은 각각 두 번 실행되었으므로 캐시 된 성능을 보게됩니다. 캐시 된 상태와 캐시되지 않은 상태를 기준으로 한 실적 변화는 전체적으로 다음과 같은 주제가됩니다.

dellstore2=# EXPLAIN ANALYZE SELECT * FROM customers WHERE customerid IN 
    (SELECT customerid FROM orders WHERE orderid<2); 
Nested Loop (cost=8.27..16.56 rows=1 width=268) (actual time=0.051..0.060 rows=1 loops=1) 
    -> HashAggregate (cost=8.27..8.28 rows=1 width=4) (actual time=0.028..0.030 rows=1 loops=1) 
     -> Index Scan using orders_pkey on orders (cost=0.00..8.27 rows=1 width=4) (actual time=0.011..0.015 rows=1 loops=1) 
       Index Cond: (orderid < 2) 
    -> Index Scan using customers_pkey on customers (cost=0.00..8.27 rows=1 width=268) (actual time=0.013..0.016 rows=1 loops=1) 
     Index Cond: (customers.customerid = orders.customerid) 
Total runtime: 0.191 ms 

dellstore2=# EXPLAIN ANALYZE SELECT * FROM customers WHERE customerid IN 
    (SELECT customerid FROM orders WHERE orderid<100); 
Nested Loop (cost=10.25..443.14 rows=100 width=268) (actual time=0.488..2.591 rows=98 loops=1) 
    -> HashAggregate (cost=10.25..11.00 rows=75 width=4) (actual time=0.464..0.661 rows=98 loops=1) 
     -> Index Scan using orders_pkey on orders (cost=0.00..10.00 rows=100 width=4) (actual time=0.019..0.218 rows=99 loops=1) 
       Index Cond: (orderid < 100) 
    -> Index Scan using customers_pkey on customers (cost=0.00..5.75 rows=1 width=268) (actual time=0.009..0.011 rows=1 loops=98) 
     Index Cond: (customers.customerid = orders.customerid) 
Total runtime: 2.868 ms 

dellstore2=# EXPLAIN ANALYZE SELECT * FROM customers WHERE customerid IN 
    (SELECT customerid FROM orders WHERE orderid<1000); 
Hash Semi Join (cost=54.25..800.13 rows=1000 width=268) (actual time=4.574..80.319 rows=978 loops=1) 
    Hash Cond: (customers.customerid = orders.customerid) 
    -> Seq Scan on customers (cost=0.00..676.00 rows=20000 width=268) (actual time=0.007..33.665 rows=20000 loops=1) 
    -> Hash (cost=41.75..41.75 rows=1000 width=4) (actual time=4.502..4.502 rows=999 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 24kB 
     -> Index Scan using orders_pkey on orders (cost=0.00..41.75 rows=1000 width=4) (actual time=0.056..2.487 rows=999 loops=1) 
       Index Cond: (orderid < 1000) 
Total runtime: 82.024 ms 

dellstore2=# EXPLAIN ANALYZE SELECT * FROM customers WHERE customerid IN 
    (SELECT customerid FROM orders WHERE orderid<10000); 
Hash Join (cost=443.68..1444.68 rows=8996 width=268) (actual time=79.576..157.159 rows=7895 loops=1) 
    Hash Cond: (customers.customerid = orders.customerid) 
    -> Seq Scan on customers (cost=0.00..676.00 rows=20000 width=268) (actual time=0.007..27.085 rows=20000 loops=1) 
    -> Hash (cost=349.97..349.97 rows=7497 width=4) (actual time=79.532..79.532 rows=7895 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 186kB 
     -> HashAggregate (cost=275.00..349.97 rows=7497 width=4) (actual time=45.130..62.227 rows=7895 loops=1) 
       -> Seq Scan on orders (cost=0.00..250.00 rows=10000 width=4) (actual time=0.008..20.979 rows=9999 loops=1) 
        Filter: (orderid < 10000) 
Total runtime: 167.882 ms