12.2. Tablas e índices #

12.2.1. Buscar en una tabla
12.2.2. Crear índices

Los ejemplos de la sección anterior ilustraron la coincidencia de texto completo utilizando cadenas constantes simples. Esta sección muestra cómo buscar datos de tablas, opcionalmente utilizando índices.

12.2.2. Crear índices #

Podemos crear un índice GIN (Section 12.9) para acelerar las búsquedas de texto:

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', body));

Observa que se utiliza la versión de 2 argumentos de to_tsvector. Solo las funciones de búsqueda de texto que especifican un nombre de configuración se pueden usar en índices de expresiones (Section 11.7). Esto se debe a que el contenido del índice no debe verse afectado por default_text_search_config. Si se vieran afectados, el contenido del índice podría ser inconsistente porque diferentes entradas podrían contener tsvectors creados con diferentes configuraciones de búsqueda de texto, y no habría forma de adivinar cuál es cuál. Sería imposible volcar y restaurar dicho índice correctamente.

Debido a que en el índice anterior se utilizó la versión de dos argumentos de to_tsvector, solo una referencia de consulta que use la versión de 2 argumentos de to_tsvector con el mismo nombre de configuración utilizará ese índice. Es decir, WHERE to_tsvector('english', body) @@ 'a & b' puede usar el índice, but WHERE to_tsvector(body) @@ 'a & b' cannot. This ensures that an index will be used only with the same configuration used to create the index entries.

Es posible configurar índices de expresiones más complejos en los que el nombre de la configuración se especifique mediante otra columna, por ejemplo:

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector(config_name, body));

donde config_name es una columna en la tabla pgweb. Esto permite configuraciones mixtas en el mismo índice mientras se registra qué configuración se utilizó para cada entrada del índice. Esto sería útil, por ejemplo, si la colección de documentos contuviera documentos en diferentes idiomas. Nuevamente, las consultas que están destinadas a usar el índice deben estar redactadas de manera que coincidan, por ejemplo, WHERE to_tsvector(config_name, body) @@ 'a & b'.

Los índices pueden incluso concatenar columnas:

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

Otro enfoque consiste en crear una columna tsvector separada para contener la salida de to_tsvector. Para mantener esta columna automáticamente actualizada con sus datos de origen, usa una columna generada almacenada. Este ejemplo es una concatenación de title y body, utilizando coalesce para asegurar que un campo se siga indexando cuando el otro sea NULL:

ALTER TABLE pgweb
    ADD COLUMN textsearchable_index_col tsvector
               GENERATED ALWAYS AS (to_tsvector('english', coalesce(title, '') || ' ' || coalesce(body, ''))) STORED;

Luego creamos un índice GIN para acelerar la búsqueda:

CREATE INDEX textsearch_idx ON pgweb USING GIN (textsearchable_index_col);

Ahora estamos listos para realizar una búsqueda rápida en texto completo:

SELECT title
FROM pgweb
WHERE textsearchable_index_col @@ to_tsquery('create & table')
ORDER BY last_mod_date DESC
LIMIT 10;

Una ventaja del enfoque de columna separada sobre un índice de expresión es que no es necesario especificar explícitamente la configuración de búsqueda de texto en las consultas para poder utilizar el índice. Como se muestra en el ejemplo anterior, la consulta puede depender de default_text_search_config. Otra ventaja es que las búsquedas serán más rápidas, ya que no será necesario volver a realizar las llamadas a to_tsvector para verificar las coincidencias del índice. (Esto es más importante cuando se utiliza un índice GiST que uno GIN; consulta la Section 12.9). Sin embargo, el enfoque de índice de expresión es más fácil de configurar y requiere menos espacio en disco, ya que la representación tsvector no se almacena explícitamente.