Postgres tìm kiếm toàn văn bản với nhiều cột, tại sao concat trong chỉ mục và không chạy trong thời gian chạy?


10

Tôi đã bắt gặp tìm kiếm toàn văn bản trong các bài đăng trong vài ngày qua và tôi hơi bối rối về việc lập chỉ mục khi tìm kiếm trên nhiều cột.

Các tài liệu postgres nói về việc tạo một ts_vectorchỉ mục trên các cột được nối, như vậy:

CREATE INDEX pgweb_idx ON pgweb 
    USING gin(to_tsvector('english', title || ' ' || body));

mà tôi có thể tìm kiếm như vậy:

... WHERE 
      (to_tsvector('english', title||' '||body) @@ to_tsquery('english', 'foo'))

Tuy nhiên, nếu tôi muốn đôi khi chỉ tìm kiếm tiêu đề, đôi khi chỉ là phần thân và đôi khi cả hai, tôi sẽ cần 3 chỉ mục riêng biệt. Và nếu tôi thêm vào cột thứ ba, đó có thể là 6 chỉ mục, v.v.

Một cách khác mà tôi chưa thấy trong các tài liệu chỉ là lập chỉ mục hai cột riêng biệt, và sau đó chỉ sử dụng một WHERE...ORtruy vấn bình thường :

... WHERE
      (to_tsvector('english', title) @@ to_tsquery('english','foo'))
    OR
      (to_tsvector('english', body) @@ to_tsquery('english','foo'))

Điểm chuẩn của hai hàng trên ~ 1 triệu dường như về cơ bản không có sự khác biệt về hiệu suất.

Vì vậy, câu hỏi của tôi là:

Tại sao tôi muốn nối các chỉ mục như thế này, thay vì chỉ lập các cột riêng lẻ? Những lợi thế / bất lợi của cả hai là gì?

Dự đoán tốt nhất của tôi là nếu tôi biết trước tôi sẽ chỉ muốn tìm kiếm cả hai cột (không bao giờ một cột), tôi sẽ chỉ cần một chỉ mục bằng cách ghép mà sử dụng ít bộ nhớ hơn.


Tôi không thực sự chắc chắn làm thế nào ghép nối titlevào bodyvà sau đó lập chỉ mục sẽ mang lại nhiều giá trị, mặc dù tôi sẵn sàng điều chỉnh. Tôi có lẽ sẽ chỉ gắn bó với việc lập chỉ mục chúng một cách riêng biệt. Ngoài ra, nếu đó là một lần lập dị mà bằng cách nào đó yêu cầu bạn ghép nối, thì tôi đoán bạn chỉ có thể chạy truy vấn đặc biệt.
swasheck

Bạn đoán đúng. Tôi sẽ khuyến khích bạn tự trả lời nếu không có ai khác, phong cách Jeopardy ở đây.
jcolebrand

Câu trả lời:


3

Không, bạn không cần các chỉ mục riêng biệt. Sử dụng tính năng cân. Chúng chỉ là một nhãn mà bạn có thể truy vấn. Bạn có thể có tối đa bốn nhãn để truy vấn (AD).

--search any "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick'::tsquery; --true

--search B "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:B'::tsquery; --false

--search B or C "fields" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:BC'::tsquery; --true

Bạn có thể muốn nối các tsvector, để bạn có thể áp dụng riêng các trọng số cho chúng và sau đó đặt chúng lại với nhau:

select
  setweight( name_column::tsvector, 'A') || setweight( phone_column::tsvector, 'B');

2

Trên thực tế, sự thay thế sẽ là sử dụng ở đâu với OR , và không phải AND .

Nếu bạn có chỉ mục trên tsvector (body + title) và bạn đang tìm kiếm trong đó, các từ được tìm kiếm có thể ở tiêu đề HOẶC trong thân.

Ngoài ra - khi kiểm tra, hãy đảm bảo bạn có số lượng hàng hợp lý trong bảng.

Trường hợp đơn giản nhất sẽ cho thấy sự khác biệt tốt: tìm hai từ - một trong số đó rất có khả năng là trong tiêu đề. và cái khác - đó là rất có khả năng trong cơ thể. Nhưng hãy chắc chắn rằng không có nhiều hàng phù hợp với cả hai tiêu chí. Ví dụ: bạn có thể có 30% từ "depesz" trong cơ thể. Bạn cũng có ~ 30% cơ hội có "mysql" trong tiêu đề. Nhưng việc có "depesz và mysql" trong bất kỳ trường nào trong cùng một hàng là rất khó xảy ra. Và sau đó kiểm tra hiệu suất với các chỉ số như vậy.


Ha, điểm tốt, trên OR vs VÀ tôi sẽ cập nhật câu hỏi. Tôi đã làm điều đó với 1 triệu hàng - không thể bận tâm chờ thêm nữa để chèn :)
latentflip

1
Cảm ơn bạn đã ghé thăm depesz - chúng tôi đang nhận được khá nhiều câu hỏi về postgres trong những ngày này vì vậy tôi hy vọng bạn sẽ tiếp tục :-)
Jack nói hãy thử topanswers.xyz 23/03

@Jack: không chắc chắn tôi sẽ làm - Tôi thấy các trang web stackexchange ngày càng ít sử dụng hơn. Tôi thường cố gắng để có được RSS, nhưng trên các trang web stackexchange rss khá vô dụng - rất nhiều ô nhiễm từ phiên bản của các câu hỏi cũ.

Tôi đã tạo một nguồn cấp dữ liệu rss cho bạn ở đây - bạn có sẵn sàng thử không? Tôi rất vui khi nỗ lực trong việc lọc ra những thứ mà bạn không có hứng thú để có cơ hội tham gia nhiều hơn vào trang web :-)
Jack nói hãy thử topanswers.xyz

Jack :) Tôi sẽ cắn - đăng ký.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.