Présentation des requêtes

Cette page décrit la fonction SEARCH et le mode de requête amélioré, qui sont permettant d'effectuer une recherche en texte intégral sur les tables Spanner.

Interroger un index de recherche

Spanner fournit SEARCH à utiliser pour les requêtes d'index de recherche. Un exemple de cas d'utilisation serait application dans laquelle les utilisateurs saisissent du texte dans un champ de recherche et l'application envoie l'entrée utilisateur directement dans la fonction SEARCH. La fonction SEARCH utiliserait ensuite un indice de recherche pour trouver ce texte.

La fonction SEARCH nécessite deux arguments:

  • Nom d'un index de recherche
  • Requête de recherche brute

La fonction SEARCH ne fonctionne que lorsqu'un index de recherche est défini. SEARCH peut être combinée à n'importe quelle construction SQL arbitraire, telle que des filtres, des agrégations ou des jointures.

La fonction SEARCH ne peut pas être utilisée avec des requêtes de transaction.

La requête suivante utilise la fonction SEARCH pour renvoyer tous les albums dont le titre contient friday ou monday :

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')

Requêtes de recherche brutes et langage rquery

Le deuxième argument de la fonction SEARCH est une requête de recherche brute. Spanner utilise un langage spécifique au domaine (DSL) appelé rquery.

Le langage rquery suit les mêmes règles que l'analyseur lexical en texte brut lors de la division de la chaîne d'entrée en termes distincts. Cela inclut la segmentation des langues asiatiques.

Pour en savoir plus sur l'utilisation de rquery, consultez syntaxe rquery.

Mode Requête amélioré

Spanner propose deux modes de recherche en texte intégral: un mode de recherche de base la recherche Google et un mode plus avancé appelé enhance_query. Lorsque cette option est activée, enhance_query étend la requête de recherche pour y inclure des termes associés et des synonymes, ce qui augmente la probabilité de trouver des résultats pertinents.

Pour activer cette option, définissez l'argument facultatif enhance_query=>true dans la fonction SEARCH. Par exemple, la requête de recherche hotl cal correspond à l'album Hotel California.

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)

Le mode enhance_query est une option au moment de la requête. Cela n'a aucune incidence sur la tokenisation. Vous pouvez utiliser le même index de recherche avec ou sans enhance_query.

Google améliore constamment ses algorithmes d'amélioration des requêtes. Par conséquent, une requête avec enhance_query == true peut générer des résultats légèrement différents au fil du temps.

Lorsque le mode enhance_query est activé, cela peut augmenter le nombre de termes recherchée par la fonction SEARCH, ce qui pourrait légèrement augmenter la latence.

Par exemple, la requête suivante utilise un délai avant expiration de trois secondes et échoue si enhance_query n'est pas disponible :

@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'fast car', enhance_query=>true)

Pour en savoir plus sur l'utilisation de l'option enhance_query, consultez la fonction SEARCH.

Exigences concernant les requêtes SQL

Une requête SQL doit remplir plusieurs conditions pour utiliser un indice de recherche. Si ces conditions ne sont pas remplies, la requête utilise un autre plan de requête ou échoue si aucun autre plan n'existe.

Les requêtes doivent remplir les conditions suivantes:

  • Les fonctions SEARCH et SEARCH_SUBSTRING nécessitent un index de recherche. Spanner n'est pas compatible avec ces fonctions dans les requêtes adressées à la table de base ou aux index secondaires.

  • Pour les index partitionnés, toutes les colonnes de partition doivent être liées par une condition d'égalité dans la clause WHERE de la requête.

    Par exemple, si un indice de recherche est défini sur PARTITION BY x, y, la requête doit comporter un conjoncteur dans la clause WHERE de x = <parameter or constant> AND y = <parameter or constant>. Cet index de recherche pris en compte par l'optimiseur de requêtes si une telle condition est manquante.

  • Toutes les colonnes TOKENLIST référencées par les opérateurs SEARCH et SEARCH_SUBSTRING doivent être indexées dans le même indice de recherche.

    Prenons l'exemple de la définition de table et d'index suivante:

    CREATE TABLE Albums (
        AlbumId STRING(MAX) NOT NULL,
        AlbumTitle STRING(MAX),
        AlbumStudio STRING(MAX),
        AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
        AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN
      ) PRIMARY KEY(AlbumId);
    
      CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens);
      CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);
    

    La requête suivante échoue, car aucun index de recherche unique n'est indexe à la fois AlbumTitle_Tokens et AlbumStudio_Tokens:

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
    
  • Si la colonne d'ordre de tri est nullable, le schéma et la requête doivent exclure les lignes où la colonne d'ordre de tri est NULL. Pour en savoir plus, consultez la section Ordre de tri de l'index de recherche.

  • Si l'index de recherche est filtré NULL, la requête doit inclure le même Expression de filtrage NULL utilisée dans un index. Pour en savoir plus, consultez la section Index de recherche filtré par NULL.

  • Les index de recherche et les fonctions de recherche ne sont pas compatibles avec le langage LMD, le langage LMD partitionné ni les requêtes partitionnées.

  • Les index de recherche et les fonctions de recherche sont généralement utilisés dans les transactions en lecture seule. Si les exigences de l'application autorisent les résultats obsolètes, nous vous recommandons d'exécuter des requêtes de recherche avec une durée d'obsolescence d'au moins 10 secondes. Pour en savoir plus, consultez la section Lire des données obsolètes. C'est particulièrement utile pour les requêtes de recherche volumineuses qui sont distribuées vers plusieurs Paxos groupes.

    Les index de recherche et les fonctions de recherche ne sont pas recommandés dans les transactions en lecture-écriture. Pendant l'exécution, les requêtes de recherche verrouillent l'intégralité d'une partition d'index. en tant que Résultat, un taux élevé de requêtes de recherche dans les transactions en lecture-écriture peut entraîner des conflits de verrouillage entraînant des pics de latence. Par défaut, les index de recherche automatiquement sélectionné dans les transactions en lecture/écriture. Si une requête est obligée de utilise un index de recherche dans une transaction en lecture-écriture, il échoue par défaut. Il va échouent également si la requête contient l'une des fonctions de recherche. Ce comportement peut être ignoré avec l'indice au niveau de l'instruction @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE} (mais les requêtes sont toujours sujettes à des conflits de verrouillage).

Une fois que les conditions d'éligibilité de l'index sont remplies, l'optimiseur de requêtes tente d'accélérer les conditions de requête non textuelles (comme Rating > 4). Si l'index de recherche n'inclut pas la colonne TOKENLIST appropriée, la condition n'est pas accélérée et reste une condition résiduelle.

Paramètres de requête

rquery et d'autres paramètres tels que OFFSET sont spécifiés sous la forme d'un littéral ou Un paramètre de requête. Nous vous recommandons d'utiliser des paramètres de requête pour la recherche dans le texte intégral plutôt que des littéraux de chaîne.

Sélection d'index

Spanner sélectionne généralement l'index le plus efficace pour une requête à l'aide de la modélisation basée sur les coûts. Cependant, la suggestion FORCE_INDEX indique explicitement Spanner pour utiliser un index de recherche spécifique. Par exemple, l'exemple suivant montre comment forcer Spanner à utiliser AlbumsIndex :

SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

Si l'index de recherche spécifié n'est pas éligible, la requête échoue, même si d'autres index de recherche éligibles sont disponibles.

Extraits dans les résultats de recherche

Un extrait est un texte extrait d'une chaîne donnée qui donne aux utilisateurs une une idée du contenu d'un résultat de recherche et de la raison pour laquelle il est pertinentes par rapport à leur requête.

Par exemple, Gmail utilise des extraits pour indiquer la partie d'un e-mail qui correspond à la requête de recherche :

Liste des extraits

Le fait que la base de données génère un extrait présente plusieurs avantages:

  1. Pratique : vous n'avez pas besoin d'implémenter de logique pour générer des extraits à partir d'une requête de recherche.
  2. Efficacité : les extraits réduisent la taille de sortie du serveur.

La fonction SNIPPET crée l'extrait. Elle renvoie la partie pertinente la valeur de la chaîne d'origine ainsi que les positions des caractères à mettre en surbrillance. La le client peut ensuite choisir comment présenter l'extrait de code à l'utilisateur final (par exemple, en utilisant du texte en surbrillance ou en gras). La fonction SNIPPET supprime toutes les balises HTML de la chaîne d'origine.

Par exemple, la commande suivante utilise SNIPPET pour récupérer du texte à partir de AlbumTitle :

SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")

Étape suivante