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 pour les requêtes d'index de recherche. La fonction SEARCH nécessite deux arguments:

  • Un nom dans l'index de recherche
  • Une requête rquery

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 requête suivante utilise la fonction SEARCH pour renvoyer tous les albums dont le contenu friday ou monday dans le titre:

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

Le langage rquery

Le deuxième argument de la fonction SEARCH est un langage spécifique au domaine (DSL) appelée rquery. Le langage rquery est similaire à celui des internautes avez l'habitude d'utiliser sur google.com:

  • L'utilisation de plusieurs termes implique AND. Par exemple, "Big Time" équivaut à big AND time.
  • L'opération OR implique une disjonction entre deux termes, tels que big OR time. L'instruction SEARCH(tl, 'big time OR fast car') équivaut à:

    SEARCH(tl, 'big')
    AND (SEARCH(tl, 'time')
         OR SEARCH(tl, 'fast'))
    AND SEARCH(tl, 'cat');
    

    OR ne s'applique qu'aux deux conditions adjacentes. Par exemple, la recherche l'expression happy friday OR monday recherche tous les documents dont le contenu le terme happy, et soit le terme friday, soit le terme monday.

  • Les guillemets doubles correspondent à une recherche d'expression exacte. Par exemple, le rquery "big cat" correspond à "I have a big cat", mais pas à "My cat is big".

  • L'opérateur AROUND fait correspondre les termes qui se trouvent à une certaine distance les uns des autres. Par exemple, la requête big AROUND cat correspond à "big, white et duveteux", mais ne correspond pas à "gros chien était assis à côté d'un petit chat". Par défaut, les recherches s'appliquent aux termes séparés par cinq positions au maximum. À pour ajuster la distance, transmettez un argument à l'opérateur AROUND. Spanner accepte deux syntaxes pour AROUND:

    • big AROUND(10) cat
    • big AROUND 10 cat
  • L'opérateur AROUND, lorsqu'il est utilisé dans une expression, peut faire correspondre des termes situés à une certaine distance les uns des autres et dans le même ordre (cinq jetons par défaut). Par exemple, la chaîne big AROUND cat correspond "grand chat blanc et duveteux", mais pas "chat était grand".

  • La négation d'un seul jeton est exprimée par un tiret (-). Exemple : -dog correspond à tous les documents qui ne contiennent pas le terme dog.

  • La ponctuation est généralement ignorée. Par exemple, "Big Time!" est équivalent à "Big Time".

  • La recherche n'est pas sensible à la casse. Par exemple, "Big Time" correspond à "big time".

  • Les opérateurs The OR et AROUND sont sensibles à la casse. La barre verticale (|) est un raccourci pour OR.

Fonctionnement du langage rquery

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

De nombreuses applications permettent aux utilisateurs de saisir une requête de recherche dans un champ de recherche. Le moyen le plus simple d'intégrer ces requêtes d'utilisateurs finaux consiste à envoyer l'entrée utilisateur directement dans la fonction SEARCH.

Le tableau suivant explique la signification des différentes chaînes rquery:

rquery Explication
Big Cat Fait correspondre les documents qui contiennent les deux termes "grand" et "chat".
cat OR dog Correspond aux documents qui contiennent au moins l'un des termes "chat" et "chien".
-cat Renvoie tous les documents qui ne contiennent pas le terme "chat".
"big dog" -"big cat" Fait correspondre les documents qui contiennent deux termes adjacents "grand" et "chien", mais qui ne contiennent pas le mot "grand" à côté et "chat". Par exemple, cette requête correspond à "I have a big dog and a small cat", mais ne correspond pas à "I have a big dog and a small cat", mais ne renvoie pas à "I have a big dog and a small cat", un grand chien et un grand chat".
cat|dog C'est la même chose que chat OR chien.
and OR or Correspond aux documents contenant le terme "et" ou le terme « ou » (l'opérateur OR doit être en majuscules)

Mode de requête amélioré

En plus de la recherche en texte intégral basée sur des jetons uniquement, Spanner est compatible avec un mode plus riche appelé enhance_query. Lorsqu'il est activé, ce mode étend la requête de recherche pour inclure plus de variantes de jeton. Ces réécritures augmentent rappel.

Pour activer cette option, définissez l'argument facultatif enhance_query=>true dans 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'affecte pas 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. En tant que résultat, une requête avec enhance_query == true peut donner un résultat légèrement différent résultats au fil du temps...

Lorsque le mode enhance_query est activé, cela peut augmenter le nombre de termes recherché par la fonction SEARCH, ce qui peut entraîner une augmentation 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, 'cat', enhance_query=>true)

Exigences concernant les requêtes SQL

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

Les requêtes doivent remplir les conditions suivantes:

  • Les fonctions SEARCH et SEARCH_SUBSTRING nécessitent un index de recherche. Spanner n'accepte pas ces fonctions dans les requêtes sur la table de base ou les index secondaires. Requêtes sur
  • Index partitionnés toutes les colonnes de partition doivent être liées par une condition d'égalité dans le WHERE de la requête.

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

  • Toutes les colonnes TOKENLIST référencées par SEARCH et SEARCH_SUBSTRING doivent être indexés dans le même index 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 il n'existe pas d'index de recherche unique qui 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 peut avoir une valeur nulle, le schéma et la requête doivent tous les deux exclure les lignes dont la colonne d'ordre de tri est NULL. Voir Ordre de tri de l'index de recherche pour en savoir plus.

  • 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. Voir une recherche filtrée par valeur NULL index pour en savoir plus.

  • Les index de recherche ne sont pas compatibles avec le LMD, le LMD partitionné et le LMD partitionné .

  • Les index de recherche sont généralement utilisés dans transactions en lecture seule. Si les exigences de l'application permettent d'obtenir des résultats obsolètes, nous vous recommandons d'exécuter des campagnes pour les requêtes dont la durée d'obsolescence est supérieure ou égale à 10 secondes. Pour plus pour en savoir plus, consultez 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 ne sont pas recommandés dans 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. Ce comportement peut être ignoré à l'aide de 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 les conditions d'éligibilité de l'index remplies, l'optimiseur de requête 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 demeure 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 plutôt que des littéraux de chaîne. Paramétrisé les requêtes sont plus performantes de succès de cache, ce qui entraîne la latence des requêtes et l'utilisation globale du processeur.

Par exemple, au lieu d'utiliser une requête comme celle-ci:

SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, 'cat')

utilisez la syntaxe suivante:

SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p)

Spanner exécute l'optimiseur de requêtes sur du texte SQL distinct. Moins textes SQL distincts utilisés par l'application, moins la requête l'optimisation est appelée.

Ordre de tri de l'index de recherche

Le comportement de l'ordre de tri des index de recherche est différent de celui des secondaires index.

Prenons l'exemple du tableau suivant:

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumName STRING(MAX),
  AlbumName_Token TOKENLIST AS (TOKEN(AlbumName)) HIDDEN
) PRIMARY KEY(AlbumId);

L'application peut définir un index secondaire pour rechercher des informations à l'aide de la méthode AlbumName, trié par ReleaseTimestamp:

CREATE INDEX AlbumsSecondaryIndex ON Albums(AlbumName, ReleaseTimestamp DESC);

L'index de recherche équivalent se présente comme suit (il utilise des mots clés exacts la tokenisation, car les index secondaires ne prennent pas en charge les recherches en texte intégral):

CREATE SEARCH INDEX AlbumsSearchIndex
ON Albums(AlbumName_Token)
ORDER BY ReleaseTimestamp DESC;

L'ordre de tri des index de recherche doit respecter les règles suivantes:

  1. N'utilisez des colonnes INT64 que pour l'ordre de tri d'un indice de recherche. Les colonnes dont la taille est arbitraire en utilisent trop ressources dans l'index de recherche, car Spanner doit stocker le docid à côté de chaque jeton. Plus précisément, la colonne d'ordre de tri ne peut pas utiliser Le type TIMESTAMP, car TIMESTAMP utilise une précision à la nanoseconde, ce qui ne tient pas dans un entier de 64 bits.
  2. Les colonnes d'ordre de tri ne doivent pas être NULL. Il existe deux façons d'y parvenir exigence:

    1. Déclarez NOT NULL comme colonne d'ordre de tri.
    2. Configurez l'index pour exclure les valeurs NULL.

En pratique, un code temporel est souvent utilisé pour déterminer l'ordre de tri. Une approche est d'utiliser microsecondes puisque le système Unix epoch pour ces horodatages.

Les applications récupèrent généralement d'abord les données les plus récentes à l'aide d'un indice de recherche trié par ordre décroissant.

Sélection des 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, ci-dessous montre comment forcer Spanner à utiliser AlbumsIndex:

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

Si l'index de recherche spécifié n'est pas éligible, la propriété la requête échoue, même s'il existe d'autres index de recherche éligibles.

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.

Gmail utilise par exemple 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. Commodité: vous n'avez pas besoin d'implémenter une logique pour générer des extraits. à partir d'une requête de recherche.
  2. Efficacité: les extraits de code réduisent la taille de la 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, le code suivant 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