2012-06-04 8 views
9

PostgreSQL全文検索(pg_search gemを使用)とsolr(sunspot_solr gem)のパフォーマンスをテストしています。適切な全文索引Rails/PostgreSQL/pg_search

400万レコードの場合、私はTsearchため13456ミリ秒とSOLR800ミリ秒を取得しています(つまり、SOLRクエリ+ DBのretrivalです)。索引が必要であることは明らかですが、全文検索用の作成方法はわかりません。調査したところ、全文検索ではGINインデックスを使用するべきであることがわかりました。

execute "CREATE INDEX products_gin_title ON products USING GIN(to_tsvector('english', title))" 

しかし、私は2つの以上の列を経由して探していると私は多値インデックスを必要と私はそれを実装する方法がわからないのですか?私はDB部分に慣れていません。マイサーチコードは次のようになります。

@results = Product.search_title(params[:search_term]).where("platform_id=? AND product_type=?", params[:platform_id], params[:type_id]).limit(10).all 

どのように私は状況のこのタイプのための適切なクエリを作成するのですか?

ここには、検索用語のためのレールからのSQL出力があります。

Product Load (12494.0ms) 
SELECT 
    "products".*, 
    (ts_rank((to_tsvector('simple', coalesce("products"."title"::text, ''))), (to_ tsquery('simple', ''' ' || 'car' || ' ''')), 2)) AS pg_search_rank 
FROM "products" 
WHERE (((to_tsvector('simple', coalesce("products"."tit le"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'car' || ' ''')))) 
    AND (platform_id='26' AND product_type='2') 
ORDER BY pg_search_rank DESC, "products"."id" ASC 
LIMIT 10 

編集:私は、PostgreSQL 8.4.11を使用しています

EXPLAIN ANALYZE出力は以下の通りです。

Limit (cost=108126.34..108126.36 rows=10 width=3824) (actual time=12228.736..12228.738 rows=10 loops=1) 
-> Sort (cost=108126.34..108163.84 rows=14999 width=3824) (actual time=12228.733..12228.734 rows=10 loops=1) 
    Sort Key: (ts_rank(to_tsvector('simple'::regconfig, COALESCE((title)::text, ''::text)), '''car'''::tsquery, 2)), id 
    Sort Method: top-N heapsort Memory: 18kB 
    -> Seq Scan on products (cost=0.00..107802.22 rows=14999 width=3824) (actual time=7.532..12224.585 rows=977 loops=1) 
     Filter: ((platform_id = 26) AND (product_type = 2) AND (to_tsvector('simple'::regconfig, COALESCE((title)::text, ''::text)) @@ '''car'''::tsquery)) 

Total runtime: 12228.813 ms 
+0

投稿されたクエリに加えて、あなたのPgバージョン、変更したpostgresql.confパラメータなどの 'EXPLAIN ANALYZE'の出力を投稿してください。 –

答えて

8

この式:

to_tsvector('simple', (COALESCE(title::TEXT), '')) 

はあなたのインデックスに対して検索引数可能ではありません。

クエリで使用されているまさにその式にインデックスを宣言する必要があります。

CREATE INDEX products_gin_title 
ON products 
USING GIN(to_tsvector('simple', COALESCE(title::TEXT,''))) 

(またはルビーがインデックスに使用されている式を生成します)。

あなたは複数の列をインデックスしたい場合は、単にそれらを連結:

CREATE INDEX products_gin_title 
ON products 
USING GIN(to_tsvector('simple', title || ' ' || product_type || ' ' || platform_id)) 

が、再び、Rubyは有用であることがインデックスのためにまったく同じ表現をフィルタリングする必要があります。

+0

敬具一列インデックスがうまくいきましたクエリ時間は80 msです。いいよ!これに加えて、それがマルチカラムインデックスであれば、速度をさらに上げることができますか?あなたがそれらを連結すると、私は検索用語にFKidsを連結して全文検索を行うべきですか? –

+0

@ドルフィン:どの 'FK ids'? – Quassnoi

+0

この例では、フルテキストでタイトルを検索していますが、product_type、platform_id(FKsを参照)で結果を絞り込んでいます。私はあなたがそのクエリで使用されるすべての列のインデックスを追加する必要がある特定のクエリをスピードアップしたい場合、印象を受けています。 –