Búsqueda de texto completo de Postgres con varias columnas, ¿por qué concat en el índice y no en tiempo de ejecución?

10

Me he encontrado con la búsqueda de texto completo en postgres en los últimos días, y estoy un poco confundido acerca de la indexación cuando busco en varias columnas.

Los documentos de postgres hablan sobre la creación de un ts_vectoríndice en columnas concatenadas, así:

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

que puedo buscar así:

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

Sin embargo, si quisiera a veces buscar solo el título, a veces solo el cuerpo, y a veces ambos, necesitaría 3 índices separados. Y si agregué en una tercera columna, eso podría ser 6 índices, y así sucesivamente.

Una alternativa que no he visto en los documentos es simplemente indexar las dos columnas por separado, y luego usar una WHERE...ORconsulta normal :

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

La comparación de los dos en ~ 1 millón de filas parece no tener básicamente ninguna diferencia en el rendimiento.

Entonces mi pregunta es:

¿Por qué querría concatenar índices como este, en lugar de simplemente indexar columnas individualmente? ¿Cuáles son las ventajas / desventajas de ambos?

Mi mejor conjetura es que si supiera de antemano que solo querría buscar ambas columnas (nunca una a la vez), solo necesitaría un índice por concatenación que use menos memoria.

latentflip
fuente
No estoy realmente seguro de cómo concatenar titleen bodyy luego indexar eso daría mucho valor, aunque estoy abierto a la corrección. Probablemente me limitaría a indexarlos por separado. Además, si fue una locura única que de alguna manera requirió que se concatenara, entonces supongo que podría ejecutar la consulta ad-hoc.
swasheck
Tienes razón en tu suposición. Te animo a que respondas si nadie más lo hace, al estilo Jeopardy aquí.
jcolebrand

Respuestas:

3

No, no necesitas índices separados. Utiliza la función de pesas. Son solo una etiqueta con la que puede consultar. Puede tener hasta cuatro etiquetas para consultar (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

Es posible que desee concatenar tsvectors, de modo que pueda aplicarles pesos por separado y luego juntarlos:

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

En realidad, la alternativa sería usar where con OR , y no AND .

Si tiene un índice en tsvector (cuerpo + título) y está buscando en él, las palabras buscadas pueden estar en el título O en el cuerpo.

Además, cuando realice la prueba, asegúrese de tener un número razonable de filas en la tabla.

El caso más simple que debería mostrar una buena diferencia: encuentra dos palabras, una de las cuales es muy probable que esté en el título. y el otro, es muy probable que esté en el cuerpo. Pero asegúrese de que no haya muchas filas que coincidan con ambos criterios. Por ejemplo, puede tener el 30% de la palabra "depesz" en el cuerpo. También tienes ~ 30% de posibilidades de tener "mysql" en el título. Pero tener "depesz y mysql" en cualquiera de los campos de la misma fila es muy poco probable. Y luego verifique el rendimiento con dichos índices.


fuente
Ja, buen lugar, en OR vs AND actualizaré la pregunta. Lo hice con 1 millón de filas, no podía molestarme esperando que insertaran más :)
latentflip
1
Gracias por pasar por Depesz, estamos recibiendo bastantes preguntas de postgres en estos días, así que espero que te
quedes
@Jack: no estoy seguro de que lo haga. Encontré sitios de intercambio de pila cada vez menos utilizables. Por lo general, trato de obtener RSS, pero en los sitios de stackexchange rss es bastante inútil, tanta contaminación por la edición de viejas preguntas.
He creado un feed rss para usted aquí . ¿Está dispuesto a intentarlo? Estoy feliz de hacer el esfuerzo de filtrar cosas en las que es poco probable que te interese para tener la oportunidad de involucrarte más en el sitio :-)
Jack dice que intente topanswers.xyz
Jack :) Voy a morder - suscrito.