Возможно, я задаю не тот вопрос в названии. Вот факты:
Мои специалисты по обслуживанию клиентов жалуются на медленное время отклика при поиске клиентов в интерфейсе администрирования нашего сайта на Django.
Мы используем Postgres 8.4.6. Я начал регистрировать медленные запросы и обнаружил этого преступника:
SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')
Этот запрос занимает более 32 секунд для выполнения. Вот план запроса, предоставленный EXPLAIN:
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 QuerySet, сгенерированный приложением Django Admin, я не имею никакого контроля над самим запросом. Индекс кажется логичным решением. Я попытался создать индекс, чтобы ускорить это, но это не имело значения:
CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))
Что я делаю неправильно? Как я могу ускорить этот запрос?
Этот индекс не поможет, потому что в начале вашего совпадения есть «%» - индекс BTREE может соответствовать только префиксам, а подстановочный знак в начале вашего запроса означает, что нет фиксированного префикса для поиска.
Вот почему он выполняет сканирование таблицы и сопоставляет каждую запись по очереди со строкой запроса.
Вам, вероятно, нужно взглянуть на использование полнотекстового индекса и операторов сопоставления текста, а не выполнять поиск по подстроке с LIKE, которым вы являетесь в данный момент. Вы можете найти больше о полнотекстовом поиске в документации:
http://www.postgresql.org/docs/8.4/static/textsearch-intro.html
На самом деле, на этой странице я заметил, что LIKE, по-видимому, никогда не использует индексы, что мне кажется странным, поскольку он должен иметь возможность разрешать префиксы без подстановочных знаков, используя индекс BTREE. Несколько быстрых тестов показывают, что документация, вероятно, верна, но в этом случае никакое количество индексации не поможет, пока вы используете LIKE для разрешения запроса.
источник
%
роль является необходимой функцией: представителям службы поддержки клиентов она нужна для поиска учетных записей клиентов, особенно если в адресе электронной почты есть опечатка.