PostgreSQL: разница в производительности NOT IN и EXCEPT (отредактировано # 2)

У меня есть два запроса, которые функционально идентичны. Один из них работает очень хорошо, другой - очень плохо. Я не понимаю, откуда возникает разница в производительности.

Запрос №1:

SELECT id 
FROM subsource_position
WHERE
  id NOT IN (SELECT position_id FROM subsource)

Это возвращается со следующим планом:

                                  QUERY PLAN                                   
-------------------------------------------------------------------------------
 Seq Scan on subsource_position  (cost=0.00..362486535.10 rows=128524 width=4)
   Filter: (NOT (SubPlan 1))
   SubPlan 1
     ->  Materialize  (cost=0.00..2566.50 rows=101500 width=4)
           ->  Seq Scan on subsource  (cost=0.00..1662.00 rows=101500 width=4)

Запрос №2:

SELECT id FROM subsource_position
EXCEPT
SELECT position_id FROM subsource;

План:

                                           QUERY PLAN                                            
-------------------------------------------------------------------------------------------------
 SetOp Except  (cost=24760.35..25668.66 rows=95997 width=4)
   ->  Sort  (cost=24760.35..25214.50 rows=181663 width=4)
         Sort Key: "*SELECT* 1".id
         ->  Append  (cost=0.00..6406.26 rows=181663 width=4)
               ->  Subquery Scan on "*SELECT* 1"  (cost=0.00..4146.94 rows=95997 width=4)
                     ->  Seq Scan on subsource_position  (cost=0.00..3186.97 rows=95997 width=4)
               ->  Subquery Scan on "*SELECT* 2"  (cost=0.00..2259.32 rows=85666 width=4)
                     ->  Seq Scan on subsource  (cost=0.00..1402.66 rows=85666 width=4)
(8 rows)

У меня такое чувство, что я ' m отсутствует либо что-то явно плохое в одном из моих запросов, либо я неправильно настроил сервер PostgreSQL. Я ожидал, что это НЕ В будет хорошо оптимизировать; НЕ В всегда является проблемой производительности или есть причина, по которой он не оптимизируется здесь?

Дополнительные данные:

=> select count(*) from subsource;
 count 
-------
 85158
(1 row)

=> select count(*) from subsource_position;
 count 
-------
 93261
(1 row)

Изменить : Я исправил проблему AB! = BA, упомянутую ниже . Но моя проблема, как указано, все еще существует: запрос №1 по-прежнему значительно хуже, чем запрос №2. Я считаю, что это следует из того факта, что в обеих таблицах одинаковое количество строк.

Edit 2 : Я использую PostgresQL 9.0.4. Я не могу использовать EXPLAIN ANALYZE, потому что запрос №1 занимает слишком много времени. Все эти столбцы НЕ НУЛЕНЫ, поэтому в результате не должно быть никакой разницы.

Редактировать 3 : У меня есть индекс для обоих этих столбцов. Мне еще не удалось выполнить запрос №1 (сдался примерно через 10 минут). Запрос №2 возвращается немедленно.

25
задан Daniel Lyons 19 August 2011 в 20:00
поделиться