Postgres pencarian teks lengkap dengan banyak kolom, mengapa concat dalam indeks dan tidak pada saat runtime?

10

Saya telah menemukan pencarian teks lengkap di postgres dalam beberapa hari terakhir, dan saya agak bingung tentang pengindeksan ketika mencari di beberapa kolom.

Postgres docs berbicara tentang menciptakan ts_vectorindeks pada kolom bersambung, seperti:

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

yang bisa saya cari seperti ini:

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

Namun, jika saya ingin kadang-kadang mencari hanya judul, kadang-kadang hanya tubuh, dan kadang-kadang keduanya, saya akan membutuhkan 3 indeks terpisah. Dan jika saya menambahkan di kolom ketiga, itu berpotensi menjadi 6 indeks, dan seterusnya.

Alternatif yang belum saya lihat dalam dokumen adalah hanya untuk mengindeks dua kolom secara terpisah, dan kemudian hanya menggunakan WHERE...ORpermintaan normal :

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

Membandingkan dua baris pada ~ 1 juta baris pada dasarnya tidak memiliki perbedaan dalam kinerja.

Jadi pertanyaan saya adalah:

Mengapa saya ingin menggabungkan indeks seperti ini, daripada hanya mengindeks kolom secara individual? Apa kelebihan / kekurangan keduanya?

Tebakan terbaik saya adalah bahwa jika saya tahu sebelumnya saya hanya ingin mencari kedua kolom (tidak pernah satu per satu) saya hanya akan memerlukan satu indeks dengan menggabungkan yang menggunakan lebih sedikit memori.

latentflip
sumber
Saya tidak benar-benar yakin bagaimana menggabungkan titleke dalam bodydan kemudian pengindeksan yang akan memberi banyak nilai, meskipun saya terbuka untuk koreksi. Saya mungkin hanya akan tetap dengan mengindeks mereka secara terpisah. Juga, jika itu adalah beberapa kali aneh yang entah bagaimana mengharuskan Anda untuk menyatukan, maka saya kira Anda bisa menjalankan kueri ad-hoc.
swasheck
Anda benar dalam tebakan Anda. Saya akan mendorong Anda untuk menjawab sendiri jika tidak ada orang lain yang melakukannya, gaya Jeopardy di sini.
jcolebrand

Jawaban:

3

Tidak, Anda tidak perlu indeks terpisah. Gunakan fitur bobot. Itu hanya label yang bisa Anda tolak. Anda dapat memiliki hingga empat label untuk ditanyakan (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

Anda mungkin ingin menyatukan vektor, sehingga Anda dapat secara terpisah menerapkan bobotnya dan kemudian menyatukannya:

select
  setweight( name_column::tsvector, 'A') || setweight( phone_column::tsvector, 'B');
Neil McGuigan
sumber
2

Sebenarnya alternatifnya adalah menggunakan di mana dengan OR , dan bukan AND .

Jika Anda memiliki indeks pada tsvector (tubuh + judul), dan Anda mencari di dalamnya, kata-kata yang dicari bisa dalam judul ATAU di dalam tubuh.

Juga - saat menguji, pastikan Anda memiliki jumlah baris yang masuk akal dalam tabel.

Kasus paling sederhana yang harus menunjukkan perbedaan yang baik: temukan dua kata - salah satunya yang sangat mungkin dalam judul. dan yang lainnya - yang sangat mungkin ada di dalam tubuh. Tetapi pastikan tidak banyak baris yang cocok dengan kedua kriteria. Misalnya - Anda mungkin memiliki 30% kata "depesz" di badan. Anda juga memiliki ~ 30% kemungkinan memiliki "mysql" dalam judul. Tetapi memiliki "depesz dan mysql" di salah satu bidang di baris yang sama sangat tidak mungkin. Dan kemudian periksa kinerja dengan indeks tersebut.


sumber
Ha, tempat yang bagus, pada ATAU vs DAN saya akan memperbarui pertanyaan. Saya melakukannya dengan 1 juta baris - tidak dapat diganggu menunggu untuk memasukkan lagi :)
latentflip
1
Terima kasih telah mengunjungi depesz - kami mendapatkan beberapa pertanyaan postgres akhir-akhir ini, jadi saya harap Anda akan tetap tinggal :-)
Jack berkata coba topanswers.xyz
@ Jack: tidak yakin saya akan - Saya menemukan situs stackexchange semakin tidak dapat digunakan. Saya biasanya mencoba untuk mendapatkan RSS, tetapi di situs stackexchange, rss cukup berguna - begitu banyak polusi dari edisi pertanyaan lama.
Saya telah membuat umpan rss untuk Anda di sini - apakah Anda bersedia mencobanya? Saya senang melakukan upaya dalam menyaring hal-hal yang Anda tidak mungkin tertarik untuk mendapatkan kesempatan untuk membuat Anda lebih terlibat dalam situs :-)
Jack mengatakan coba topanswers.xyz
Jack :) Saya akan menggigit - berlangganan.