2016-07-25 2 views
0

Я читаю это article и решил попробовать пример самостоятельно.Указатель cond не появился в postgres query plan

Перед добавлением индекса:

У меня есть таблицы BookHibernate, SQL был сгенерирован hibernate:

CREATE TABLE bookhibernate 
(
    book_id bigint NOT NULL, 
    bought boolean, 
    genre character varying(255), 
    name character varying(255) NOT NULL, 
    price integer NOT NULL, 
    author_id bigint, 
    CONSTRAINT bookhibernate_pkey PRIMARY KEY (book_id), 
    CONSTRAINT fk_hlepqn9vy6biuo6vn47jo5ewx FOREIGN KEY (book_id) 
     REFERENCES authorhibernate (author_id) MATCH SIMPLE 
     ON UPDATE NO ACTION ON DELETE NO ACTION, 
    CONSTRAINT fk_r9o6704wcbcawmruyqojj4nab FOREIGN KEY (author_id) 
     REFERENCES authorhibernate (author_id) MATCH SIMPLE 
     ON UPDATE NO ACTION ON DELETE NO ACTION 
) 
WITH (
    OIDS=FALSE 
); 

Так я назвал explain analyze:

explain analyze select * from bookhibernate where bookhibernate.price > 10 

Это дает мне:

"Seq Scan on bookhibernate (cost=0.00..1.02 rows=1 width=1053) (actual time=0.007..0.008 rows=2 loops=1)" 
" Filter: (price > 10)" 
"Planning time: 0.054 ms" 
"Execution time: 0.021 ms" 

После добавления индекса:

create index my_index on bookhibernate(price); 

После добавления индекса и выполнения той же explain analyze я вижу, что execution plan не изменился и я вижу Filter: (price > 10) регистр, но я ожидал увидеть Index cond: (price > 10).

Почему мое ожидание не удается?

ОБНОВЛЕНО:

мне сказали, что это из-за небольшого размера таблицы. Это звучит разумно, и это правда. Но я попробовал свой запрос против таблицы из 1000 строк.

  1. Почему Postgres решит использовать Фильтрацию? Почему это предпочтительнее?
  2. Что за сценой Filter: (price > 10)? В чем сложность этого алгоритма?
+0

Есть ли данные в вашей таблице? Вы запустили 'анализ' на столе? – jmelesky

+0

@jmelesky, да, две строки/да –

+0

Для двух строк база данных никогда не будет использовать индекс. –

ответ

1

Размер таблицы настолько мал, что для PostgreSQL более эффективно выполнять последовательное сканирование, чем использовать индекс. Если вы хотите, чтобы PostgreSQL вообще рассматривал индекс, добавьте больше строк в таблицу.

Не только размер таблицы, но и избирательность условия влияют на решение оптимизатора, следует ли использовать индекс или нет. Если у многих книг есть price больше 10, менее эффективно использовать сканирование индекса, поскольку это связано с случайным вводом-выводом (страницы индекса не сохраняются на диске последовательно). В этом случае последовательное сканирование всегда более эффективно.

Существует несколько параметров конфигурации PostgreSQL, которые влияют на то, насколько вероятен PostgreSQL для выбора индекса, наиболее важным из которых является random_page_cost.

Вы можете проверить, подходит ли ваш индекс, установив enable_seqscan = off, а затем снова выполнив запрос EXPLAIN. С помощью этого параметра PostgreSQL будет использовать сканирование индекса, если это вообще возможно.

+0

Спасибо, я вижу суть. Я попытался запустить запрос против 1000 строк, а 'Postgres' решил, что лучше фильтровать, чтобы использовать двоичный поиск с индексом. Почему это произошло? Когда индексным алгоритмом является 'lg (n)', что является сложностью алгоритма для 'Filter: (price> 10)'? –

+0

Я улучшил ответ. Выбор одной записи индекса - «O (ln (n))», но сканирование соответствующей части индекса - нет. –