PostgreSQL: Почему этот простой запрос не использует индекс?

У меня есть таблица t со столбцом c, который является int и имеет индекс btree.

Почему следующий запрос не использует этот индекс?

explain select c from t group by c;

В результате я получаю:

HashAggregate  (cost=1005817.55..1005817.71 rows=16 width=4)
  ->  Seq Scan on t  (cost=0.00..946059.84 rows=23903084 width=4)

Мое понимание индексов ограничено, но я думал, что такие запросы были целью индексов.


person David    schedule 04.02.2011    source источник


Ответы (3)


Запрос, безусловно, может использовать индекс. Причина, по которой этого не происходит в вашем конкретном случае, зависит от конкретного размера и распределения данных. Вы можете использовать SET enable_seqscan TO off для расследования.

person Peter Eisentraut    schedule 06.02.2011
comment
При каких обстоятельствах отказ от индекса не окупится? Я не могу представить себе какое-либо распределение, по крайней мере, когда мы говорим о размере в этом примере. - person David; 24.03.2011
comment
@David: сканирование всего индекса намного дороже, чем последовательное сканирование таблицы. Индекс обычно полезен только в том случае, если вы выбираете небольшое подмножество таблицы. - person Peter Eisentraut; 26.03.2011
comment
Это просто неправильно. Такой запрос, как SELECT DISTINCT x FROM t;, должен иметь возможность использовать индекс для (x). Чтение всего индекса должно быть дешевле, чем чтение всей таблицы. Но Postgres не реализовал, насколько мне известно, сканирование свободного индекса - person ypercubeᵀᴹ; 21.05.2015

Этот запрос можно выполнить с помощью оптимизации, называемой сканированием свободного индекса. Однако PostgreSQL еще не реализует эту оптимизацию, поэтому вместо этого использует сканирование таблицы.

Насколько мне известно, из основных баз данных только MySQL имеет реализовано свободное сканирование индекса (возможно, Oracle тоже?). В PostgreSQL не реализована эта функция.

person Mark Byers    schedule 04.02.2011
comment
Архитектура Postgresql означает, что в настоящее время она ДОЛЖНА посещать таблицу, даже если она использует индекс. Это намного дороже, если вам все равно нужно нажимать каждую строку. Я предполагаю, что в mysql движок должен включать закрывающие индексы для правильной работы, но я не очень хорошо знаю mysql. - person Scott Marlowe; 05.02.2011
comment
@Scott Marlowe: Но главное в том, что если можно использовать нечеткое сканирование индекса, вам не нужно нажимать каждую строку. Вот почему MySQL может быть в сотни или тысячи раз быстрее, чем PostgreSQL для такого рода запросов (в очень больших таблицах, где очень мало различных значений c). Это запрос функции с низким приоритетом, потому что простое изменение дизайна схемы (введение новой таблицы) решает проблему. - person Mark Byers; 05.02.2011
comment
Это также называется сканированием только индекса, и Oracle, SQL Server и DB2 также реализуют его. Но я сомневаюсь, что он делает запрос в тысячи раз быстрее. Быстрее, да. Но не в таком порядке (но я согласен, что действительно жаль, что у Postgres этого нет) - person a_horse_with_no_name; 05.02.2011
comment
@a_horse_with_no_name: Нет, сканирование только индекса - это нечто совершенно иное и дает лишь очень небольшое ускорение. Неплотное сканирование индекса может дать улучшение на несколько порядков. Для одного миллиона строк и 100 различных значений запрос в SQL Server может занять около 1 секунды, а в MySQL - всего несколько миллисекунд. В Oracle есть сканирование с пропуском индекса, что почти то же самое, но я не уверен, что здесь можно использовать план запроса сканирования с пропуском индекса - я думаю, что в запросе нужно ссылаться как минимум на два столбца. Однако основной алгоритм примерно такой же. - person Mark Byers; 05.02.2011

Поскольку для этого требуется сканирование всей таблицы, выполнение этого через индекс не имеет смысла. («Покрывающие индексы» бесполезны в качестве метода повышения производительности в PostgreSQL из-за его реализации MVCC).

person araqnid    schedule 04.02.2011
comment
PostgreSQL 9.2 будет включать сканирование только индекса: wiki.postgresql.org/ wiki / - person qerub; 30.08.2012