Как создать индекс, чтобы ускорить агрегат, как запрос на выражение?

dba.stackexchange https://dba.stackexchange.com/questions/4521

Вопрос

Я могу задать неправильный вопрос в названии. Вот факты:

Мои люди по обслуживанию клиентов жаловались на медленное время отклика при поиске клиентов на интерфейсе администрирования нашего сайта на основе Django.

Мы используем Postgres 8.4.6. Я начал регистрировать медленные запросы и обнаружил этого виновника:

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

Этот запрос занимает более 32 секунд. Вот план запроса, предоставленный объяснением:

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

Поскольку это запрос, генерируемый Django Orm из запроса Django, сгенерированного приложением администратора Django, у меня нет никакого контроля над самим запросом. Индекс выглядит как логическое решение. Я попытался создать индекс, чтобы ускорить это, но это не изменило:

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

Что я делаю не так? Как я могу ускорить этот запрос?

Это было полезно?

Решение

Нет индексной поддержки LIKE / ILIKE в Postgresql 8.4 - кроме оставлены на якоре поисковых терминов.

С Postgresql 9.1 Дополнительный модуль pg_trgm Предоставляет классы операторов для индексов триграмм джина и GIST поддержки LIKE / ILIKE или регулярные выражения (операторы ~ и друзья). Установите один раз на базу данных:

CREATE EXTENSION pg_trgm;

Пример индекса джина:

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

Связанный:

Другие советы

Этот индекс не поможет из -за «%» в начале вашего матча - индекс Btree может соответствовать только префиксам, а подстановка в начале вашего запроса означает, что нет фиксированного префикса.

Вот почему он делает сканирование таблицы и соответствует каждой записи по очереди на строку запроса.

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

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top