Recherche plein texte Postgres avec plusieurs colonnes, pourquoi concaténer dans l'index et pas au moment de l'exécution?

10

J'ai rencontré la recherche en texte intégral dans postgres au cours des derniers jours, et je suis un peu confus quant à l'indexation lors de la recherche sur plusieurs colonnes.

Les documents postgres parlent de la création d'un ts_vectorindex sur des colonnes concaténées, comme ceci:

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

que je peux rechercher ainsi:

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

Cependant, si je voulais parfois rechercher uniquement le titre, parfois simplement le corps, et parfois les deux, j'aurais besoin de 3 index distincts. Et si j'ajoutais dans une troisième colonne, cela pourrait potentiellement être 6 index, et ainsi de suite.

Une alternative que je n'ai pas vue dans les documents est simplement d'indexer les deux colonnes séparément, puis d'utiliser simplement une WHERE...ORrequête normale :

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

L'analyse comparative des deux sur environ 1 million de lignes semble n'avoir pratiquement aucune différence de performances.

Ma question est donc:

Pourquoi voudrais-je concaténer des index comme celui-ci, plutôt que d'indexer les colonnes individuellement? Quels sont les avantages / inconvénients des deux?

Ma meilleure supposition est que si je savais à l'avance, je ne voudrais que rechercher les deux colonnes (jamais une à la fois) Je n'aurais besoin que d'un index en concaténant qui utilise moins de mémoire.

latentflip
la source
Je ne suis pas vraiment certain de la concaténation du titledans bodypuis de l'indexation qui donnerait beaucoup de valeur, même si je suis ouvert à la correction. Je me contenterais probablement de les indexer séparément. De plus, si c'était une opération unique loufoque qui vous obligeait à concaténer, je suppose que vous pourriez simplement exécuter la requête ad hoc.
swasheck
Vous avez raison dans votre supposition. Je vous encourage à répondre par vous-même si personne d'autre ne le fait, jeopardy style ici.
jcolebrand

Réponses:

3

Non, vous n'avez pas besoin d'index séparés. Utilisez la fonction de pondération. Ils ne sont qu'une étiquette contre laquelle vous pouvez interroger. Vous pouvez avoir jusqu'à quatre étiquettes pour interroger (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

Vous souhaiterez peut-être concaténer des vecteurs ts afin de pouvoir leur appliquer séparément des pondérations, puis les regrouper:

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

En fait, l'alternative serait d'utiliser où avec OU , et non ET .

Si vous avez un index sur tsvector (corps + titre) et que vous recherchez dedans, les mots recherchés peuvent être dans le titre OU dans le corps.

Aussi - lors des tests, assurez-vous d'avoir un nombre raisonnable de lignes dans le tableau.

Cas le plus simple qui devrait montrer une bonne différence: trouvez deux mots - l'un d'eux est très susceptible d'être dans le titre. et l'autre - qui est très susceptible d'être dans le corps. Mais assurez-vous qu'il n'y a pas beaucoup de lignes qui correspondent aux deux critères. Par exemple, vous pourriez avoir 30% du mot "depesz" dans le corps. Vous avez également ~ 30% de chances d'avoir "mysql" dans le titre. Mais avoir "depesz et mysql" dans l'un des champs de la même ligne est très peu probable. Et puis vérifiez les performances avec de tels index.


la source
Ha, bon endroit, sur OR vs ET je mettrai à jour la question. Je l'ai fait avec 1 million de lignes - je ne pouvais pas être dérangé d'attendre plus d'insertion :)
latentflip
1
Merci d'être passé par depesz - nous recevons pas mal de questions postgres ces jours-ci, donc j'espère que vous resterez :-)
Jack dit d'essayer topanswers.xyz
@Jack: je n'en suis pas sûr - j'ai trouvé les sites stackexchange de moins en moins utilisables. J'essaie généralement d'obtenir des flux RSS, mais sur les sites stackexchange, le rss est à peu près inutile - tellement de pollution provenant de l'édition de vieilles questions.
J'ai créé un flux rss pour vous ici - êtes-vous prêt à essayer? Je suis heureux de faire l'effort de filtrer les choses qui ne vous intéresseront probablement pas pour avoir la chance de vous impliquer davantage dans le site :-)
Jack dit d'essayer topanswers.xyz
Jack :) Je vais mordre - abonné.