to_tsquery postgres full performance postgresql solr lucene rdbms

performance - to_tsquery - postgres full text search



¿Por qué Solr es mucho más rápido que Postgres? (5)

La mayor diferencia es que un índice de Lucene / Solr es como una base de datos de tabla única sin ningún soporte para consultas relacionales (JOIN). Recuerde que un índice generalmente solo está ahí para apoyar la búsqueda y no para ser la fuente principal de los datos. Por lo tanto, su base de datos puede estar en "tercera forma normal", pero el índice se desregulará completamente y solo contendrá los datos necesarios para la búsqueda.

Otra posible razón es que las bases de datos generalmente sufren fragmentación interna, necesitan realizar demasiadas tareas de E / S semialeatorias en solicitudes enormes.

Lo que eso significa es, por ejemplo, teniendo en cuenta la arquitectura de índice de una base de datos, la consulta conduce a los índices que a su vez conducen a los datos. Si los datos para recuperar están ampliamente distribuidos, el resultado tomará mucho tiempo y eso parece ser lo que sucede en las bases de datos.

Recientemente cambié de Postgres a Solr y vi una velocidad ~ 50x en nuestras consultas. Las consultas que ejecutamos involucran múltiples rangos, y nuestros datos son listados de vehículos. Por ejemplo: "Encuentra todos los vehículos con kilometraje <50,000, $ 5,000 <precio <$ 10,000, marca = Mazda ..."

Creé índices en todas las columnas relevantes en Postgres, por lo que debería ser una comparación bastante justa. Mirando el plan de consulta en Postgres aunque todavía estaba usando solo un índice y luego escaneando (supongo que porque no podía hacer uso de todos los diferentes índices).

Tal como lo entiendo, Postgres y Solr usan estructuras de datos vagamente similares (árboles B), y ambos almacenan en caché los datos en la memoria. Entonces me pregunto de dónde viene una gran diferencia de rendimiento.

¿Qué diferencias en arquitectura explicarían esto?


Por favor, lea this y this .

Solr (Lucene) crea un índice invertido que es donde la recuperación de datos se hace bastante más rápida. read que PostgreSQL también tiene instalaciones similares, pero no estoy seguro de si lo había usado.

Las diferencias de rendimiento que observó también pueden ser contabilizadas como "¿qué se está buscando?", "¿Cuáles son las consultas del usuario?"


Primero, Solr no usa B-trees. Un índice Lucene (la biblioteca subyacente utilizada por Solr) está formado por segments solo lectura. Para cada segmento, Lucene mantiene un diccionario de términos, que consiste en la lista de términos que aparecen en el segmento, ordenados lexicográficamente. Buscar un término en este diccionario de términos se realiza mediante una búsqueda binaria, por lo que el costo de una búsqueda de un solo término es O(log(t)) donde t es el número de términos. Por el contrario, usar el índice de un RDBMS estándar cuesta O(log(d)) donde d es el número de documentos. Cuando muchos documentos comparten el mismo valor para algún campo, esto puede ser una gran ganancia.

Además, Luten committer Uwe Schindler agregó soporte para consultas de rango numérico muy efectivas hace unos años. Para cada valor de un campo numérico , Lucene almacena varios valores con diferentes precisiones. Esto permite a Lucene ejecutar consultas de rango de manera muy eficiente. Dado que su caso de uso parece aprovechar mucho las consultas de rango numérico, esto puede explicar por qué Solr es mucho más rápido. (Para obtener más información, lea los javadocs, que son muy interesantes y brindan enlaces a documentos de investigación relevantes).

Pero Solr solo puede hacerlo porque no tiene todas las restricciones que tiene un RDBMS. Por ejemplo, Solr es muy malo al actualizar un solo documento a la vez (prefiere las actualizaciones por lotes).


Realmente no dijiste mucho sobre lo que hiciste para ajustar tu instancia de PostgreSQL o tus consultas. No es inusual ver una velocidad 50 veces mayor en una consulta de PostgreSQL a través de la afinación y / o la reformulación de su consulta en un formato que optimiza mejor.

Justo esta semana había un informe en el trabajo que alguien había escrito usando Java y múltiples consultas de una manera que, según lo mucho que había llegado en cuatro horas, iba a tomar aproximadamente un mes en completarse. (Necesitaba golpear cinco tablas diferentes, cada una con cientos de millones de filas.) Lo reescribí usando varios CTE y una función de ventana para que se ejecutara en menos de diez minutos y generara los resultados deseados directamente de la consulta. Esa es una velocidad de 4400x.

Quizás la mejor respuesta a su pregunta no tiene nada que ver con los detalles técnicos de cómo se pueden realizar las búsquedas en cada producto, sino más con facilidad de uso para su caso de uso particular. Claramente, usted fue capaz de encontrar la forma más rápida de buscar con Solr con menos problemas que PostgreSQL, y es posible que no se reduzca a nada más que eso.

Incluyo un pequeño ejemplo de cómo se pueden hacer búsquedas de texto para múltiples criterios en PostgreSQL, y cómo algunos pequeños ajustes pueden hacer una gran diferencia en el rendimiento. Para mantenerlo rápido y simple, estoy ejecutando War and Peace en forma de texto en una base de datos de prueba, con cada "documento" como una sola línea de texto. Se pueden usar técnicas similares para campos arbitrarios usando el tipo hstore o las columnas JSON , si los datos deben estar definidos de manera vaga. Donde hay columnas separadas con sus propios índices, los beneficios de usar índices tienden a ser mucho más grandes.

-- Create the table. -- In reality, I would probably make tsv NOT NULL, -- but I''m keeping the example simple... CREATE TABLE war_and_peace ( lineno serial PRIMARY KEY, linetext text NOT NULL, tsv tsvector ); -- Load from downloaded data into database. COPY war_and_peace (linetext) FROM ''/home/kgrittn/Downloads/war-and-peace.txt''; -- "Digest" data to lexemes. UPDATE war_and_peace SET tsv = to_tsvector(''english'', linetext); -- Index the lexemes using GiST. -- To use GIN just replace "gist" below with "gin". CREATE INDEX war_and_peace_tsv ON war_and_peace USING gist (tsv); -- Make sure the database has statistics. VACUUM ANALYZE war_and_peace;

Una vez configurado para la indexación, muestro algunas búsquedas con recuentos de filas y tiempos con ambos tipos de índices:

-- Find lines with "gentlemen". EXPLAIN ANALYZE SELECT * FROM war_and_peace WHERE tsv @@ to_tsquery(''english'', ''gentlemen'');

84 filas, esencia: 2.006 ms, ginebra: 0.194 ms

-- Find lines with "ladies". EXPLAIN ANALYZE SELECT * FROM war_and_peace WHERE tsv @@ to_tsquery(''english'', ''ladies'');

184 filas, esencia: 3.549 ms, ginebra: 0.328 ms

-- Find lines with "ladies" and "gentlemen". EXPLAIN ANALYZE SELECT * FROM war_and_peace WHERE tsv @@ to_tsquery(''english'', ''ladies & gentlemen'');

1 fila, esencia: 0.971 ms, gin: 0.104 ms

Ahora, dado que el índice GIN era aproximadamente 10 veces más rápido que el índice GiST, podría preguntarse por qué alguien usaría GiST para indexar datos de texto. La respuesta es que GiST generalmente es más rápido de mantener. Entonces, si sus datos de texto son altamente volátiles, el índice GiST podría ganar con la carga general, mientras que el índice GIN ganaría si solo está interesado en el tiempo de búsqueda o en una carga de trabajo de lectura en su mayoría.

Sin el índice, las consultas anteriores toman entre 17.943 ms y 23.397 ms, ya que deben analizar toda la tabla y buscar coincidencias en cada fila.

La búsqueda indexada de GIN para filas con "señoras" y "caballeros" es más de 172 veces más rápida que una exploración de tabla exactamente en la misma base de datos. Obviamente, los beneficios de la indexación serían más dramáticos con documentos más grandes que los utilizados para esta prueba.

La configuración es, por supuesto, una cosa de una sola vez. Con un activador para mantener la columna tsv , cualquier cambio realizado sería instantáneamente buscable sin rehacer ninguna configuración.

Con una consulta lenta de PostgreSQL, si muestra la estructura de la tabla (incluidos los índices), la consulta problemática y el resultado de ejecutar EXPLAIN ANALYZE de su consulta, alguien casi siempre puede detectar el problema y sugerir cómo hacer que funcione más rápido.

ACTUALIZACIÓN (9 de diciembre de 2016)

No mencioné lo que solía obtener los tiempos previos, pero según la fecha, probablemente habría sido el lanzamiento principal 9.2. Me acabo de cruzar este antiguo hilo y lo intenté nuevamente en el mismo hardware utilizando la versión 9.6.1, para ver si alguno de los ajustes intermedios del rendimiento ayuda a este ejemplo. Las consultas para un solo argumento aumentaron el rendimiento en aproximadamente un 2%, pero la búsqueda de líneas con "señoras" y "caballeros" duplicó su velocidad a 0,053 ms (es decir, 53 microsegundos) al usar el índice GIN (invertido).


Solr está diseñado principalmente para buscar datos, no para almacenarlos. Esto le permite descartar gran parte de la funcionalidad requerida de un RDMS. Entonces (o más bien lucene ) se concentra en datos puramente indexados.

Como sin duda ha descubierto, Solr permite buscar y recuperar datos de su índice. Es la última capacidad (opcional) la que lleva a la pregunta natural ... "¿Puedo usar Solr como base de datos?"

La respuesta es un sí calificado, y lo remito a lo siguiente:

Mi opinión personal es que Solr se considera mejor como un caché de búsqueda entre mi aplicación y los datos que se dominan en mi base de datos. De esa manera consigo lo mejor de ambos mundos.