Ricerca di testo completo di Postgres con più colonne, perché concaticare in indice e non in fase di esecuzione?


10

Mi sono imbattuto nella ricerca full-text in postgres negli ultimi giorni e sono un po 'confuso riguardo all'indicizzazione durante la ricerca su più colonne.

I documenti di postgres parlano della creazione di un ts_vectorindice su colonne concatenate, in questo modo:

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

che posso cercare in questo modo:

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

Tuttavia, se a volte volessi cercare solo il titolo, a volte solo il corpo, a volte entrambi, avrei bisogno di 3 indici separati. E se aggiungessi in una terza colonna, potrebbero essere potenzialmente 6 indici e così via.

Un'alternativa che non ho visto nei documenti è solo quella di indicizzare le due colonne separatamente e quindi usare solo una WHERE...ORquery normale :

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

Il benchmarking dei due su ~ 1 milione di file sembra non avere praticamente alcuna differenza nelle prestazioni.

Quindi la mia domanda è:

Perché dovrei concatenare gli indici in questo modo, piuttosto che indicizzare le colonne singolarmente? Quali sono i vantaggi / gli svantaggi di entrambi?

La mia ipotesi migliore è che se avessi saputo in anticipo avrei sempre voluto cercare entrambe le colonne (mai una alla volta) avrei bisogno di un solo indice concatenando quale usa meno memoria.


In realtà non sono certo come concatenando il titlenel bodye quindi indicizzare che possa dare molto valore, anche se io sono aperto a correzione. Probabilmente mi limiterei a indicizzarli separatamente. Inoltre, se è stato un po 'stravagante che in qualche modo ti ha richiesto di concatenare, quindi immagino che potresti semplicemente eseguire la query ad-hoc.
cambio

Hai ragione a tuo avviso. Ti incoraggio a rispondere autonomamente se nessun altro lo fa, stile Jeopardy qui.
jcolebrand

Risposte:


3

No, non hai bisogno di indici separati. Utilizzare la funzione pesi. Sono solo un'etichetta contro cui puoi interrogare. Puoi avere fino a quattro etichette per cui eseguire una query (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

Potresti voler concatenare tsvector, in modo da poter applicare separatamente i pesi a loro e poi metterli insieme:

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

2

In realtà l'alternativa sarebbe usare dove con OR , e non con AND .

Se hai un indice su tsvector (corpo + titolo) e stai cercando in esso, le parole cercate possono essere nel titolo O nel corpo.

Inoltre, durante il test, assicurarsi di avere un numero ragionevole di righe nella tabella.

Caso più semplice che dovrebbe mostrare una buona differenza: trova due parole, una delle quali è molto probabile che sia nel titolo. e l'altro - che è molto probabile che sia nel corpo. Ma assicurati che non ci siano molte righe che soddisfino entrambi i criteri. Ad esempio, potresti avere il 30% della parola "depesz" nel corpo. Hai anche ~ il 30% di probabilità di avere "mysql" nel titolo. Ma avere "depesz e mysql" in uno dei campi nella stessa riga è molto improbabile. E quindi controllare le prestazioni con tali indici.


Ah, buon posto, su OR vs E aggiornerò la domanda. L'ho fatto con 1 milione di righe - non poteva essere disturbato in attesa di altri da inserire :)
latentflip

1
Grazie per essere passato da depesz - stiamo ricevendo alcune domande postgres in questi giorni, quindi spero che resterai in giro :-)
Jack dice che prova topanswers.xyz il

@Jack: non sono sicuro che lo farò - ho trovato siti di stackexchange sempre meno utilizzabili. In genere cerco di ottenere RSS, ma sui siti di stackexchange rss è praticamente inutile - così tanto inquinamento dall'edizione di vecchie domande.

Ho creato un feed rss per te qui - sei disposto a provarlo? Sono felice di fare lo sforzo di filtrare le cose che difficilmente ti interessano per avere la possibilità di coinvolgerti maggiormente nel sito :-)
Jack dice che prova topanswers.xyz il

Jack :) Mi morderò - abbonato.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.