2012-06-04 53 views
9

PostgreSQL tam metin araması (pg_search gem kullanarak) ve solr (sunspot_solr gem) için performans test ediyorum.Uygun Tam Metin Dizini Rails/PostgreSQL/pg_search

4000000 kayıtları için ben tsearch için 13456 ms ve solr ile 800 ms alıyorum (yani SOLR sorgu + DB retrival olan). İndekse ihtiyaç duyduğum açık ama tam metin araması için nasıl bir tane oluşturacağımı bilmiyorum. Araştırdım ve tam metin araması için GIN indeksini kullanmalıyım.

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

Ama iki daha fazla sütun aracılığıyla arıyorum ve ben çok değer endeksi ihtiyaç ve bunu nasıl uygulanacağı emin değilim? DB bölümüne çok aşina değilim.

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

nasıl durumlar bu tür için uygun sorgu oluştururum: gibi Arama kodu görünüyor?

Burada arama terimi araba için raylardan gelen SQL çıktısıdır.

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 

DÜZENLEME: PostgreSQL 8.4.11 kullanıyorum

, EXPLAIN ANALYZE çıkış takip ediyor.

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

Yayınlanan sorgudaki "EXPLAIN ANALYZE" işlevinin çıktısını yayınlamaya devam edin, ayrıca Pg sürümünüz, değiştirdiğiniz herhangi bir postgresql.conf params vb. –

cevap

8

Bu ifade:

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

endeksinize karşı sargable değildir.

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

(veya yakut endeksinde kullanılan ifade oluşturmak olun):

Sen sorgusunda kullanılan tam olarak bu ifadeye endeksi beyan etmelidir.

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

ama yine Yakut endeksi için de aynı ifadeyi üzerinde filtreleme gereken kullanım olmak:

Birden sütunlar dizine eklenmesini istiyorsanız

, sadece bunları bağlamak.

+0

Sorgulama süresi yalnızca 80 ms değerindeyken tek sütun dizini çalıştı. Güzel! Buna ek olarak, bu soru hızınızı daha da artırmak için çoklu sütun indeksi mi olmalı? Onları birleştirdiğinizde, bu, FK ids’i arama terimimle birleştirerek tam metin araması yapmam gerektiği anlamına mı geliyor? –

+0

@Dolphin: hangi 'FK ids'? – Quassnoi

+0

Bu örnekte tam metinle başlık aramaktayım ve sonuçları da product_type, platform_id (belirtilen FK'ler) ile daraltmaktayım. Belirli bir sorguyu hızlandırmak istiyorsanız, o sorguda kullanılan TÜM sütunlar için dizin eklemeniz gerektiği izlenimi uyandırıyor. –