2012-08-25 17 views
6

Tôi có một truy vấn với một số thử nghiệm các lĩnh vực một cái gì đó như thế này:PostgreSQL iLike so TSEARCH

SELECT * FROM some-table 
    WHERE field1 ILIKE "%thing%" 
    OR field2 ILIKE "%thing" 
    OR field3 ILIKE "%thing"; 

Các cột được khá nhiều tất cả varchar (50) hoặc ở vùng lân cận. Bây giờ tôi hiểu để cải thiện hiệu suất tôi nên lập chỉ mục các lĩnh vực mà hoạt động tìm kiếm hoạt động. Tôi có nên xem xét thay thế ILIKE bằng TSEARCH hoàn toàn không?

Trả lời

15

Thiết lập tìm kiếm văn bản đầy đủ không giống với "chứa" như truy vấn. Nó bắt nguồn từ vv để bạn có thể kết hợp "xe hơi" với "xe hơi".

Nếu bạn thực sự muốn có một ILIKE nhanh thì không có chỉ mục cơ sở dữ liệu chuẩn hoặc FTS sẽ trợ giúp. May mắn thay, mô-đun pg_trgm có thể làm điều đó.

+0

pg_trgm rất hữu ích. Đối với người dùng Django: chỉ mục trên 'upper (your_text_field)' vì Django phát hành 'upper (x) như upper (y)' query thay vì 'ilike'. Nếu trường được lập chỉ mục mà không có 'upper' thì chỉ mục sẽ không được sử dụng trong các truy vấn đó. – Risadinha

5

Một điều đó là rất quan trọng: NO B-TREE INDEX bao giờ sẽ cải thiện loại tìm kiếm:

where field ilike '%SOMETHING%' 

Những gì tôi nói là nếu bạn làm một:

create index idx_name on some_table(field); 

Quyền truy cập duy nhất bạn sẽ cải thiện là where field like 'something%'. (khi bạn tìm kiếm các giá trị bắt đầu với một số chữ). Vì vậy, bạn sẽ không nhận được lợi ích nào bằng cách thêm chỉ mục thông thường vào cột field trong trường hợp này.

Nếu bạn cần cải thiện thời gian phản hồi tìm kiếm của mình, hãy cân nhắc sử dụng TÌM KIẾM TÌM KIẾM ĐẦY ĐỦ.

+0

Bạn đúng là không có B-Tree nào cải thiện tìm kiếm đó, nhưng PostgreSQL có thể sử dụng các loại chỉ mục khác để hỗ trợ điều kiện '% foobar%' (xem câu trả lời của Richard) –

3

Thêm một chút với những gì người khác đã nói.

Trước tiên, bạn không thể thực sự sử dụng chỉ mục dựa trên giá trị ở giữa chuỗi. Chỉ mục là tìm kiếm cây nói chung, và bạn không có cách nào để biết liệu tìm kiếm của bạn sẽ nhanh hơn chỉ quét bảng, do đó PostgreSQL sẽ mặc định là quét seq. Chỉ mục sẽ chỉ được sử dụng nếu chúng khớp với phần đầu tiên của chuỗi. Vì vậy:

SELECT * FROM invoice 
    WHERE invoice_number like 'INV-2012-435%' 

có thể sử dụng chỉ mục nhưng like '%44354456%' không thể.

Nói chung trong LedgerSMB, chúng tôi sử dụng cả hai, tùy thuộc vào loại tìm kiếm chúng tôi đang thực hiện. Bạn có thể thấy tìm kiếm như:

select * from parts 
    WHERE partnumber ilike ? || '%' 
    and plainto_tsquery(get_default_language(), ?) @@ description; 

Vì vậy, chúng rất khác nhau. Sử dụng mỗi một nơi mà nó có ý nghĩa nhất.

+1

Tôi đồng ý rằng không có đủ thông tin để chắc chắn liệu trigram hoặc tsearch có phù hợp hơn hay không, nhưng một hoặc khác (hoặc có thể là một kết hợp) dường như được chỉ ra. – kgrittn