2012-06-04 43 views
9

我正在测试PostgreSQL全文搜索(使用pg_search gem)和solr(sunspot_solr gem)的性能。正确的全文索引Rails/PostgreSQL/pg_search

400万条记录我得到13456毫秒TSEARCH800毫秒SOLR(即SOLR查询+ DB retrival)。很明显,我需要索引,但我不知道如何创建一个全文搜索。我调查并发现,对于全文搜索,我应该使用GIN索引。

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

但是我通过两列搜索,我需要多值索引,我不知道如何实现它?我对DB部分不是很熟悉。我的搜索代码如下所示:

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

如何创建这种类型的情况下,适当的查询?

以下是来自rails for search term的SQL输出car

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

请在发布的查询上加上运行'EXPLAIN ANALYZE'的输出,加上您的Pg版本,您更改的任何postgresql.conf参数等。 –

回答

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)) 

但同样,红宝石应该对指数进行滤波上完全相同的表达是使用的。

+0

谢谢第一次单列索引工作查询时间是80毫秒,太好了!除此之外,对你的问题是否应该是多列索引以进一步提高速度?当你说连接它们时,这是否意味着我应该通过将FK ID连接到我的搜索项来进行全文搜索? –

+0

@Dolphin:哪个'FK ids'? – Quassnoi

+0

在此示例中,我正在通过全文搜索标题,并缩小了product_type,platform_id(提到的FK)的结果。我的印象是,如果你想加快特定的查询,你需要为该查询中使用的所有列添加索引。 –