У меня есть два запроса, которые функционально идентичны. Один из них работает очень хорошо, другой работает очень плохо. Я не вижу, откуда возникает разница в производительности.
Запрос №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)
У меня такое чувство, что у меня отсутствует либо что-то явно плохое по одному из моих запросов, либо я неправильно сконфигурировал сервер PostgreSQL. Я бы ожидал, что этот NOT IN
будет хорошо оптимизирован; NOT IN
всегда проблема производительности или есть причина, по которой она не оптимизируется здесь?
Дополнительные данные:
=> select count(*) from subsource;
count
-------
85158
(1 row)
=> select count(*) from subsource_position;
count
-------
93261
(1 row)
Изменить. Я исправил проблему A-B!= B-A, упомянутую ниже. Но моя проблема, как указано, все еще существует: запрос №1 все еще намного хуже, чем запрос №2. Это, я считаю, следует из того факта, что обе таблицы имеют одинаковое количество строк.
Изменить 2. Я использую PostgresQL 9.0.4. Я не могу использовать EXPLAIN ANALYZE, потому что запрос № 1 занимает слишком много времени. Все эти столбцы NOT NULL, поэтому в результате этого не должно быть разницы.
Изменить 3. У меня есть индекс для обоих этих столбцов. Я еще не получил запрос № 1 для завершения (сдался после ~ 10 минут). Запрос № 2 немедленно возвращается.