Acelera las expresiones de coincidencia de patrones

Los índices de búsqueda de Spanner pueden acelerar las expresiones de coincidencia de patrones, como LIKE, STARTS_WITH, ENDS_WITH y el predicado de coincidencia de expresiones regulares REGEXP_CONTAINS. En esta página, se describe cómo crear y configurar un índice de búsqueda con TOKENIZE_NGRAMS para acelerar los predicados de coincidencia de patrones.

Configura un n-grama TOKENLIST para la aceleración de la correlación de patrones

Para habilitar la aceleración de las expresiones de coincidencia de patrones, tokeniza una columna STRING en minúsculas con TOKENIZE_NGRAMS y almacena la columna STRING con la cláusula STORING en GoogleSQL o la cláusula INCLUDE en PostgreSQL.

GoogleSQL

CREATE TABLE Albums (
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Ngram_Tokens TOKENLIST AS (
  TOKENIZE_NGRAMS(LOWER(AlbumTitle), ngram_size_min=>3, ngram_size_max=>4)) HIDDEN,
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Ngram_Tokens) STORING (AlbumTitle);

PostgreSQL

CREATE TABLE albums (
albumid bigint NOT NULL,
album_title varchar,
album_title_ngrams_tokens spanner.tokenlist GENERATED ALWAYS AS (
  spanner.tokenize_ngrams(
    lower(album_title),
    ngram_size_min => 3,
    ngram_size_max => 4
  )
) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));

CREATE SEARCH INDEX albumsidx ON
albums(album_title_ngrams_tokens) INCLUDE (album_title);

Aceleración automática de consultas con predicados de coincidencia de patrones

El optimizador de consultas podría optar por acelerar las siguientes consultas con AlbumsIndex y AlbumTitle_Ngram_Tokens.

GoogleSQL

En GoogleSQL, aceleramos LIKE, STARTS_WITH, ENDS_WITH y REGEXP_CONTAINS.

  • Predicado LIKE:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE AlbumTitle LIKE "%999%";
    
  • Predicado STARTS_WITH:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE STARTS_WITH(AlbumTitle, "apple")
    
  • Predicado ENDS_WITH:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE ENDS_WITH(AlbumTitle, "apple")
    
  • Predicado REGEXP_CONTAINS:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE REGEXP_CONTAINS(AlbumTitle, r"(good|great)[ ]+morning")
    

PostgreSQL

En PostgreSQL, aceleramos LIKE y STARTS_WITH.

  • Predicado LIKE:

    SELECT albumid
    FROM albums /*@ FORCE_INDEX = albumsidx */
    WHERE album_title like '%999%';
    
  • Predicado STARTS_WITH:

    SELECT albumid
    FROM albums /*@ FORCE_INDEX = albumsidx */
    WHERE starts_with(album_title, 'apple')
    

El optimizador de consultas usa diferentes estimaciones de selectividad predeterminadas según el predicado de coincidencia de patrones. Como resultado, es posible que el optimizador seleccione un análisis de tabla completo o un análisis de índice secundario con un filtro residual en lugar del índice de búsqueda.

Si tu consulta es inesperadamente lenta, verifica el plan de ejecución. Si el optimizador no selecciona el índice de búsqueda, intenta usar @{FORCE_INDEX = AlbumsIndex} en GoogleSQL o /*@ FORCE_INDEX = albumsidx */ en PostgreSQL.

Requisitos previos sobre la aceleración

Para que Spanner habilite esta aceleración, se deben cumplir las siguientes reglas:

  • El índice debe almacenar la columna STRING con la cláusula STORING en GoogleSQL o la cláusula INCLUDE en PostgreSQL. Esto evita uniones inversas costosas a la tabla base durante el filtrado posterior, lo que es fundamental para el rendimiento cuando la búsqueda recupera demasiados documentos.
  • La columna STRING se debe tokenizar con TOKENIZE_NGRAMS.
  • La tokenización debe aplicarse a LOWER(column_name) en lugar de column_name.
  • El patrón LIKE, el prefijo STARTS_WITH, el sufijo ENDS_WITH o la expresión regular REGEXP_CONTAINS se deben especificar como un literal constante. No se admiten los parámetros de búsqueda para evitar la aceleración en patrones demasiado cortos.
  • El patrón LIKE, el prefijo STARTS_WITH, el sufijo ENDS_WITH o la expresión regular REGEXP_CONTAINS deben contener suficiente texto para, al menos, un n-grama. Por ejemplo, r".*" no cumple con los requisitos porque no hay una secuencia de caracteres que coincida. Del mismo modo, si el tamaño mínimo del n-grama se establece en 3, el predicado LIKE "%ab%" no cumple con los requisitos porque "ab" (tamaño 2) es demasiado corto.

¿Qué sigue?