2012-06-04 43 views
9

Tôi đang thử nghiệm hiệu suất cho tìm kiếm văn bản đầy đủ của PostgreSQL (sử dụng đá quý pg_search) và solr (sunspot_solr gem).Chỉ mục văn bản đầy đủ thích hợp Rails/PostgreSQL/pg_search

Đối với 4 triệu bản Tôi nhận 13.456 ms cho Tsearch800 ms với Solr (có nghĩa là Solr truy vấn + DB retrival). Rõ ràng là tôi cần chỉ mục nhưng tôi không chắc chắn cách tạo chỉ mục cho tìm kiếm toàn văn. Tôi đã điều tra và thấy rằng để tìm kiếm toàn văn tôi nên sử dụng chỉ mục GIN.

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

Nhưng tôi đang tìm kiếm thông qua hai cột nữa và tôi cần chỉ mục nhiều giá trị và tôi không biết cách triển khai? Tôi không quen thuộc với phần DB. Mã tìm kiếm của tôi trông giống như:

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

Làm cách nào để tạo truy vấn thích hợp cho loại tình huống này?

Đây là đầu ra SQL từ đường ray cho cụm từ tìm kiếm xe.

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 

EDIT:

Tôi đang sử dụng PostgreSQL 8.4.11, EXPLAIN ANALYZE đầu ra được sau.

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

Vui lòng đăng kết quả chạy 'EXPLAIN ANALYZE' trên truy vấn đã đăng, cộng với phiên bản Pg của bạn, bất kỳ thông số postgresql.conf nào bạn đã thay đổi, v.v. –

Trả lời

8

biểu này:

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

không sargable chống lại chỉ số của bạn.

Bạn nên khai báo các chỉ số trên mà biểu hiện chính xác được sử dụng trong truy vấn:

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

(hoặc làm cho ruby ​​tạo cụm từ được sử dụng trong chỉ mục).

Nếu bạn muốn nhiều cột được lập chỉ mục, chỉ cần ghép chúng:

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

nhưng một lần nữa, Ruby nên được lọc vào chính xác cùng một biểu thức cho chỉ số được sử dụng.

+0

Cảm ơn bạn đã nắm được chỉ mục cột đơn hiện đang hoạt động là 80 ms, tốt đẹp! Câu hỏi cho bạn ngoài việc này là nó nên được đa cột chỉ số để tăng thêm tốc độ? Khi bạn nói nối chúng, điều đó có nghĩa là tôi nên tìm kiếm toàn văn bằng cách ghép các id FK vào cụm từ tìm kiếm của tôi? –

+0

@Dolphin: 'Id FK' nào? – Quassnoi

+0

Trong ví dụ này, tôi đang tìm kiếm tiêu đề thông qua toàn văn, và cũng thu hẹp kết quả với product_type, platform_id (FK được đề cập). Tôi đang bị ấn tượng rằng nếu bạn muốn tăng tốc độ truy vấn cụ thể, bạn cần thêm chỉ mục cho TẤT CẢ các cột được sử dụng trong truy vấn đó. –

Các vấn đề liên quan