Мне трудно понять, что я воспринимаю как несоответствие в том, как postgres выбирают использовать индексы. У нас есть запрос на основе NOT IN
против индексированного столбца, который postgres выполняется последовательно, но когда мы выполняем тот же запрос, что и IN
, он использует индекс.Postgres противоречивое использование индекса против Seq Scan
Я создал упрощенный пример, который я считаю, демонстрирует этот вопрос, обратите внимание на этот первый запрос является последовательным
CREATE TABLE node
(
id SERIAL PRIMARY KEY,
vid INTEGER
);
CREATE INDEX x ON node(vid);
INSERT INTO node(vid) VALUES (1),(2);
EXPLAIN ANALYZE
SELECT *
FROM node
WHERE NOT vid IN (1);
Seq Scan on node (cost=0.00..36.75 rows=2129 width=8) (actual time=0.009..0.010 rows=1 loops=1)
Filter: (vid <> 1)
Rows Removed by Filter: 1
Total runtime: 0.025 ms
Но если инвертировать запрос к IN
, вы заметите, что теперь решили использовать индекс
EXPLAIN ANALYZE
SELECT *
FROM node
WHERE vid IN (2);
Bitmap Heap Scan on node (cost=4.34..15.01 rows=11 width=8) (actual time=0.017..0.017 rows=1 loops=1)
Recheck Cond: (vid = 1)
-> Bitmap Index Scan on x (cost=0.00..4.33 rows=11 width=0) (actual time=0.012..0.012 rows=1 loops=1)
Index Cond: (vid = 1)
Total runtime: 0.039 ms
Может ли кто-нибудь пролить свет на это? В частности, существует способ переписать NOT IN
для работы с индексом (когда, очевидно, набор результатов не так упрощен, как только 1 или 2).
Мы используем Postgres 9.2 на CentOS 6.6
Что произойдет, если вы напишете: 'WHERE vid NOT IN (1)'? –
Это была хорошая мысль, но, к сожалению, это не имело значения. Каким-то образом 'NOT IN' является не просто обратным« IN »с точки зрения планировщиков. – user590028
'Как-то НЕ IN - это не просто обратное к IN с точки зрения планировщиков': это правильно, так как vid NULLable. – wildplasser