2017-03-24 2 views
-1

できるだけ早くデータベースから検索結果を取得しようとしています。問題は、検索が行われるすべてのフィールドのインデックスを作成した後でも、PostgreSQLサーバから返される結果は非常に遅く、少なくとも20秒です。大規模なPostgreSQLテーブルでの検索のための適切なインデックス設定

提案がありますか?ここで

詳細

は、SQLクエリです:

SELECT COUNT(*) 
FROM "Part" 
WHERE ("part_no"='aeroflex') 
    OR ("msn"='aeroflex') 
    OR ("nsn"='aeroflex') 
    OR ("name" ILIKE '%aeroflex%') 
    OR ("manufacturer" ILIKE '%aeroflex%') 
    OR ("mfg_sku"='aeroflex') 

そしてここでここでは280万行

-- ---------------------------- 
-- Table structure for Part 
-- ---------------------------- 
DROP TABLE IF EXISTS "electronic_parts"."Part"; 
CREATE TABLE "electronic_parts"."Part" (
    "id" int4 NOT NULL DEFAULT nextval('"Part_id_seq"'::regclass), 
    "part_no" varchar COLLATE "default", 
    "manufacturer" varchar COLLATE "default", 
    "description" text COLLATE "default", 
    "slug" varchar COLLATE "default", 
    "nsn" varchar COLLATE "default", 
    "price" numeric, 
    "name" varchar COLLATE "default", 
    "mfg_sku" varchar COLLATE "default", 
    "msn" varchar COLLATE "default" 
) 
WITH (OIDS=FALSE); 
ALTER TABLE "electronic_parts"."Part" OWNER TO "root"; 

-- ---------------------------- 
-- Primary key structure for table Part 
-- ---------------------------- 
ALTER TABLE "electronic_parts"."Part" ADD PRIMARY KEY ("id") NOT DEFERRABLE INITIALLY IMMEDIATE; 

-- ---------------------------- 
-- Indexes structure for table Part 
-- ---------------------------- 
CREATE INDEX "part_i1" ON "electronic_parts"."Part" USING btree(msn COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
CREATE INDEX "part_i2" ON "electronic_parts"."Part" USING gin(to_tsvector('english'::regconfig, name::text) "pg_catalog"."tsvector_ops") WITH (FASTUPDATE = YES); 
CREATE INDEX "part_i2" ON "electronic_parts"."Part" USING gin(to_tsvector('english'::regconfig, name::text) "pg_catalog"."tsvector_ops") WITH (FASTUPDATE = YES); 
CREATE INDEX "part_i3" ON "electronic_parts"."Part" USING gin(to_tsvector('english'::regconfig, manufacturer::text) "pg_catalog"."tsvector_ops") WITH (FASTUPDATE = YES); 
CREATE INDEX "part_i3" ON "electronic_parts"."Part" USING gin(to_tsvector('english'::regconfig, manufacturer::text) "pg_catalog"."tsvector_ops") WITH (FASTUPDATE = YES); 
CREATE INDEX "part_i4" ON "electronic_parts"."Part" USING gin(to_tsvector('english'::regconfig, description) "pg_catalog"."tsvector_ops") WITH (FASTUPDATE = YES); 
CREATE INDEX "part_i4" ON "electronic_parts"."Part" USING gin(to_tsvector('english'::regconfig, description) "pg_catalog"."tsvector_ops") WITH (FASTUPDATE = YES); 
CREATE UNIQUE INDEX "part_u1" ON "electronic_parts"."Part" USING btree(part_no COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
CREATE UNIQUE INDEX "part_u2" ON "electronic_parts"."Part" USING btree(nsn COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
CREATE UNIQUE INDEX "part_u3" ON "electronic_parts"."Part" USING btree(mfg_sku COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
CREATE UNIQUE INDEX "part_u4" ON "electronic_parts"."Part" USING btree(slug COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 

で構成され、テーブルのSQLダンプはEXPLAIN

です

https://explain.depesz.com/s/5Lh

システムの仕様

DB:GCCでコンパイルはx86_64-pc-linux-gnuのようにPostgreSQLの9.5.6、(Ubuntuの5.4.0-6ubuntu1〜16.04.4)5.4.0 20160609、64ビット

OS:Ubuntuの16.04.2 LTS

RAM:512メガバイト(これは、開発目的のためだけだ)

無負荷は、サーバー上のすべてではありません。現在、1人のユーザーとしてテスト中です。

+0

いつも 'EXPLAIN ANALYZE'を追加してください質問がパフォーマンスに関連する場合のクエリの結果 - 標準の 'text_ops'演算子クラスは、パターンがアンカーされていないときに' LIKE'と 'ILIKE'クエリを助けません(' 'メーカー名' 'LIKE 'aeroflex%''を検索すると助けになるはずです。パターンは '%'で始まらず '_'でもありません)。 - ['pg_trgm'](https://www.postgresql.org/docs/current/static/pgtrgm.html)モジュールの' gin_trgm_ops'または 'gist_trgm_ops'は、これらの' ILIKE'検索に役立ちます。 – pozs

+0

[postgresql-performanceタグのinfoリンク](http://stackoverflow.com/tags/postgresql-performance/info)を読んでください。あなたの質問を編集し、それらのものを含める。 –

+0

@ MikeSherrill'CatRecall 'が私の質問を更新しました。 https://explain.depesz.com/s/5Lh – demonoid

答えて

0

クエリの次の2つの部分、つまり遅くなるのは("name" ILIKE '%aeroflex%')("manufacturer" ILIKE '%aeroflex%')です。この理由は、Postgresがないスタート文字列(すなわち、それは'aeroflex%'をスピードアップするためにインデックスを使用しますが、ない'%aeroflex%'できる。

あなたのインデックスがショーを行いiLikeの演算子で定期的にインデックスを使用することはできませんですあなたはto_tsvectorでインデックスを作成することで、この中にいくつかの研究を、でしたが、代わりに、あなたはすでに使用を作成したインデックスをto_tsvectorを利用するにはto_tsquery

で特別な演算子@@を使用する必要がこれらのインデックスをilike使用しないことaのようなwhereの制約:

where to_tsvector('english', "name") @@ to_tsquery('english', 'aeroflex') 

また、likeilikeを使用する場合は、pgtrmモジュールを使用できます。

まず:likeまたはilike

CREATE INDEX part_name_trigram_i ON "Part" USING GIN("name" gin_trgm_ops); 

であなたがフィルタリングするカラムにインデックスを追加するには、ドキュメントページから卦の詳細情報を見つけることができます。次

CREATE EXTENSION pg_trgm; 

モジュールをアクティブ化https://www.postgresql.org/docs/current/static/pgtrgm.htmlとpostgresの自然言語検索でhttps://www.postgresql.org/docs/current/static/datatype-textsearch.html

関連する問題