Полнотекстовые индексы и индексы pattern_ops - PullRequest
1 голос
/ 26 июля 2011

Я использую django, и все мои запросы создаются django, поэтому у меня нет рукописных запросов ...

У меня есть таблица BillRecords, в которой есть поле subscriberno. В моих фильтрах django я использую фильтрующий запрос как:

BillRecords.objects.filter(subscriberno__icontains='123456')

Начиная с subscriberno, клиент сказал, что это вполне укороченная версия действительного числа ...

Этот фильтр выводит запрос наподобие:

SELECT "subscriberno" FROM "BillRecords" WHERE UPPER("subscriberno"::text) LIKE UPPER(E'%123456%');

subscriberno является полем char, потому что некоторые числа содержат альфы и некоторые специальные символы.

В моей базе данных у меня есть два индекса для этого столбца, созданных моими коллегами.

"BillRecords_subscriberno" btree (subscriberno)
"BillRecords_fsubscriberno_like" btree (subscriberno varchar_pattern_ops)

Мне интересно, использование двух индексов для такого запроса логично. Поскольку весь наш фильтр django использует icontains, и это должно быть создание запросов, как я пишу выше.

Postgres анализ запроса выглядит следующим образом:

Seq Scan on BillRecords  (cost=0.00..159782.40 rows=370 width=15) (actual time=579.637..3705.079 rows=10 loops=1)
Filter: (upper((subscriberno)::text) ~~ '%123456%'::text)
Total runtime: 3705.106 ms
(3 rows)

Итак, насколько я вижу, индекс не используется. Поскольку у индекса usega есть затраты на вставку и обновление данных, наличие двух индексов без использования (насколько я могу видеть из этого анализа) показалось мне нелогичным.

Есть ли шанс, что django выведет разные запросы для аналогичного icontanis фильтра? Или мои индексы совершенно бесполезны?

Ответы [ 3 ]

1 голос
/ 26 июля 2011

Вы не можете использовать индекс для незанятого оператора like.

upper(foo) like 'bar%' -- index on upper(foo)
upper(foo) like '%bar' -- no index
reverse(upper(foo)) like 'rab%' -- index on reverse(upper(foo))
upper(foo) like '%bar%' -- no index

Но вы можете найти триграмный вклад использования, если вы хотите уменьшить окно поиска.

1 голос
/ 27 июля 2011

Простой способ проверить, используются ли ваши индексы вообще, - посмотреть на

SELECT * FROM pg_stat_user_indexes;

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

1 голос
/ 26 июля 2011

Содержит (подстрока) запросы не имеют доступа к индексам (если оператор не связан с полнотекстовым модулем). С другой стороны, запросы могут начинаться с индексов. Затраты на индексирование незначительны, если количество элементов не слишком мало и вставки обычно выполняются не большими партиями, а в сценарии OLTP.

Правильно ли я прочитал статистику: почти 4 секунды для сканирования 370 строк?

P.S. Вы могли бы рассмотреть альтернативный подход: использовать основанный на функции индекс, возможно, на последних четырех символах subscriberno, соединенных, скажем, с первыми тремя символами имени абонента, и использовать начальный с или равно вместо LIKE с поисковым термином с подстановочными знаками.

...