式の集約LIKEクエリを高速化するためにインデックスを作成する方法は?


20

タイトルに間違った質問をしている可能性があります。事実は次のとおりです。

カスタマーサービスの担当者は、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 Adminアプリケーションによって生成されたDjango QuerySetからDjango ORMによって生成されたクエリなので、クエリ自体を制御することはできません。インデックスは論理的なソリューションのようです。これを高速化するためにインデックスを作成しようとしましたが、違いはありません。

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

何が間違っていますか?このクエリを高速化するにはどうすればよいですか?

回答:


21

以下のためのインデックスのサポートはありませんLIKE/ ILIKEのPostgreSQL 8.4は -を除いて、左アンカー検索用語

ためのPostgreSQL 9.1追加モジュールはpg_trgmGINとのGiSTトリグラム支持インデックスに対して演算子クラスを提供LIKE/ ILIKEまたは正規表現(オペレータ~や友人)。データベースごとに1回インストールします。

CREATE EXTENSION pg_trgm;

GINインデックスの例:

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

関連:


2
これは実際には正しい答えです。
vonPetrushev

9

一致の先頭に '%'があるため、そのインデックスは役に立たない-BTREEインデックスはプレフィックスのみに一致し、クエリの先頭にワイルドカードがあるのは、検索する固定プレフィックスがないことを意味します。

これが、テーブルスキャンを実行し、クエリ文字列に対してすべてのレコードを順番に照合する理由です。

現在のLIKEで部分文字列検索を行うのではなく、おそらくフルテキストインデックスとテキストマッチング演算子を使用する必要があります。全文検索の詳細については、ドキュメントをご覧ください。

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

実際、私はそのページから、LIKEは明らかにインデックスを使用しないことに気付きます。これは、BTREEインデックスを使用して非ワイルドカードプレフィックスを解決できるはずなので、奇妙に思えます。ただし、いくつかの簡単なテストでは、ドキュメントがおそらく正しいことが示唆されています。その場合、LIKEを使用してクエリを解決している間、インデックス作成の量は役に立ちません。


それが私が恐れていたものです。役立つ別の種類のインデックスはありますか?先ほど言ったように、クエリ自体に影響を与える能力には少々制約があります。
デビッドエイク

また、リード%は必要な機能です。カスタマーサービス担当者は、特にメールアドレスにタイプミスがある場合に、カスタマーアカウントを見つけるためにそれを必要とします。
デビッドエイク

まあ、LIKEとフルテキストインデックス処理に関する少しの調査の後、私はあなたのポイントを見始めています。
デビッドエイク

今のところ、先頭のワイルドカードを抑制する方法を見つけました。それはあなたが判明することができますが、適切なとインデックスを作成した場合、LIKEでインデックスを使用する演算子クラス。ドキュメントはこちらです:postgresql.org/docs/8.4/static/indexes-opclass.html
デビッドエイク

また、データベースの膨張を確認してください。そのテーブルに大量の膨張がある場合、それをseqスキャンするのに長い時間がかかります。ダウンタイムが発生した場合は、主キーでクラスター化し、高速化するかどうかを確認してください。:あなたが肥大化をチェックしたい場合は、ここでは、クエリを実行し、分析を実行することができwiki.postgresql.org/wiki/Show_database_bloatを。より正確な値については、そのページの下部を参照してください。
スコットマーロウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.