インデックスを作成して、式のQueryのようなQueryをスピードアップする方法は?
-
16-10-2019 - |
質問
私はタイトルで間違った質問をしているかもしれません。これが事実です:
私のカスタマーサービスの人々は、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 Admin Applicationによって生成されたDjango QuerysetからDjango Ormによって生成されたクエリであるため、クエリ自体を制御できません。インデックスは論理的なソリューションのようです。これをスピードアップするためにインデックスを作成しようとしましたが、違いはありませんでした。
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
または正規表現(演算子 ~
と友達)。データベースごとに1回インストールします。
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
実際、私はそのページから、明らかにインデックスを使用しないように見えることに気づきました。これは、BTreeインデックスを使用して非ワイルドカードのプレフィックスを解決できるはずであるため、私には奇妙に思えます。いくつかの簡単なテストでは、ドキュメントがおそらく正しいことが示唆されていますが、その場合、クエリを解決するために使用している間、インデックスの量は役に立たないでしょう。