База данных Postgre игнорирует созданный индекс? - PullRequest
2 голосов
/ 19 мая 2010

У меня есть база данных Postgre и таблица my_table. В этой таблице 4 столбца (id, column1, column2, column3). Столбец id является первичным ключом, для столбцов нет других ограничений или индексов. В таблице около 200000 строк.

Я хочу распечатать все строки, у которых значение столбца column2 равно (без учета регистра) 'value12'. Я использую это:

SELECT * FROM my_table WHERE column2 = lower('value12')

вот план выполнения для этого оператора (результат set enable_seqscan=on; EXPLAIN SELECT * FROM my_table WHERE column2 = lower('value12')):

Seq Scan on my_table (cost=0.00..4676.00 rows=10000 width=55)
Filter: ((column2)::text = 'value12'::text)

Я считаю это медленным, поэтому я создаю индекс для столбца column2 для лучшей производительности поиска:

CREATE INDEX my_index ON my_table (lower(column2))

Теперь я запустил тот же выбор:

SELECT * FROM my_table WHERE column2 = lower('value12')

и я ожидаю, что это будет намного быстрее, потому что он может использовать индекс. Однако это не так быстро, как раньше. Поэтому я проверяю план выполнения, и он такой же, как и раньше (см. Выше). Так что он все еще использует последовательную сцену и игнорирует индекс! Где проблема?

Ответы [ 4 ]

4 голосов
/ 19 мая 2010

Это:

SELECT * 
 FROM my_table 
WHERE column2 = lower('value12')

... предполагает, что все данные в column2 строчные. Случаи, когда это не так, не совпадают.

SELECT * 
 FROM my_table 
WHERE LOWER(column2) = LOWER('value12')

Использование функции для столбца может сделать индекс бесполезным.

Решение принимается оптимизатором, который учитывает не только индексы, но и максимально быстрый результат. Насколько я понимаю, Postgres не предоставляет синтаксис для принудительного использования индекса, как вы видите в MySQL, Oracle или SQL Server.

Вы можете посмотреть, используя SET STATISTICS:

ALTER TABLE <table> ALTER COLUMN <column> SET STATISTICS <number>;

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

Ссылка: Настройка производительности PostgreSQL

2 голосов
/ 19 мая 2010

Вы на самом деле не сравниваете значения нижнего регистра column2. Вы сравниваете (буквальные) значения column2 со строчной версией значения value12.

Вы хотели сравнить с lower(column2)?

SELECT * FROM my_table WHERE lower(column2) = lower('value12')
1 голос
/ 19 мая 2010

Возможно, вам понадобится:

WHERE lower(column2) = lower('value12')

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

0 голосов
/ 19 мая 2010

В дополнение к ответам о lower(), это должно убедить PostgreSQL использовать индексы - для проверки выполните explain.

set enable_seqscan = false;

Вы также можете запустить vacuum analyze после создания индекса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...