10

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

400万レコードの場合、Tsearchで13456ミリ秒、SOLRで800ミリ秒(つまり、SOLRクエリ+ DB検索)を取得しています。インデックスが必要なことは明らかですが、全文検索用にインデックスを作成する方法がわかりません。調査したところ、全文検索には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

このタイプの状況に対して適切なクエリを作成するにはどうすればよいですか?

これは、検索語carのレールからの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
4

1 に答える 1

10

この式:

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

インデックスに対してsargableではありません。

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

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

(または、rubyにインデックスで使用される式を生成させます)。

複数の列にインデックスを付ける場合は、それらを連結するだけです。

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

しかし、繰り返しになりますが、Rubyは、インデックスを使用するためにまったく同じ式でフィルタリングする必要があります。

于 2012-06-04T11:55:38.733 に答える