Panoramica delle query

In questa pagina vengono descritti la funzione SEARCH e la modalità di query avanzata, utilizzata per eseguire una ricerca a testo intero sulle tabelle Spanner.

Eseguire una query su un indice di ricerca

Spanner fornisce SEARCH per le query dell'indice di ricerca. La funzione SEARCH richiede due argomenti:

  • Un nome di indice di ricerca
  • Una query rquery

La funzione SEARCH funziona solo quando viene definito un indice di ricerca. La funzione SEARCH può essere combinata con qualsiasi costrutto SQL arbitrario, ad esempio filtri, aggregazioni o join.

La seguente query utilizza la funzione SEARCH per restituire tutti gli album con friday o monday nel titolo:

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

Il linguaggio rquery

Il secondo argomento della funzione SEARCH è una lingua specifica del dominio (DSL) denominato rquery. Il linguaggio rquery è simile al linguaggio degli utenti internet che abitualmente usano su google.com:

  • Più termini implicano AND. Ad esempio, "Big Time" equivale a big AND time.
  • L'operazione OR implica una disgiunzione tra due termini, ad esempio big OR time. L'istruzione SEARCH(tl, 'big time OR fast car') equivale a:

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

    OR si applica solo ai due termini adiacenti. Ad esempio, la ricerca l'espressione happy friday OR monday cerca tutti i documenti contenenti il termine happy e il termine friday o monday.

  • Le virgolette doppie indicano una ricerca di una frase. Ad esempio, la query rquery "big cat" corrisponde a "Ho un grande gatto", ma non a "Il mio gatto è grande".

  • L'operatore AROUND trova corrispondenze con i termini che si trovano entro una certa distanza da tra loro. Ad esempio, rquery big AROUND cat corrisponde a "big, white, gatto morbido", ma non corrisponde a "un cane grande era seduto accanto a un gatto piccolo". Per impostazione predefinita, vengono utilizzati termini separati da al massimo cinque posizioni. Per regolare la distanza, passa un argomento all'operatore AROUND. Spanner supporta due sintassi per AROUND:

    • big AROUND(10) cat
    • big AROUND 10 cat
  • L'operatore AROUND, se utilizzato all'interno di una frase, può trovare corrispondenze tra termini che si trovano a una determinata distanza l'uno dall'altro e nello stesso ordine (il valore predefinito è cinque token). Ad esempio, la stringa big AROUND cat corrisponde a "gatto grande bianco e soffice", ma non a "il gatto era grande".

  • La negazione di un singolo token è espressa con un trattino (-). Ad esempio, -dog corrisponde a tutti i documenti che non contengono il termine dog.

  • Generalmente la punteggiatura viene ignorata. Ad esempio, "Big Time!". equivale a "Big Time".

  • La ricerca non fa distinzione tra maiuscole e minuscole. Ad esempio, "Big Time" corrisponde a "big time".

  • Gli operatori The OR e AROUND sono sensibili alle maiuscole. Il carattere barra verticale (|) è una scorciatoia per OR.

Come funziona il linguaggio rquery

Il linguaggio rquery segue le stesse regole tokenizzatore di testo normale quando suddividi la stringa di input in termini distinti. È inclusa la segmentazione delle lingue asiatiche.

Molte applicazioni offrono agli utenti un modo per inserire una query di ricerca in una casella di ricerca. Il modo più semplice per integrare queste query degli utenti finali è inviare l'input dell'utente direttamente alla funzione SEARCH.

La seguente tabella spiega il significato di varie stringhe rquery:

rquery Spiegazione
Big Cat Restituisce i documenti che contengono entrambi i termini "grande" e "gatto".
cat OR dog Corrisponde ai documenti che contengono almeno uno dei termini "gatto" e "cane".
-cat Corrisponde a tutti i documenti che non contengono il termine "gatto".
"big dog" -"big cat" Restituisce i documenti che contengono due termini adiacenti "grandi" e "cane", ma non contengono elementi "big" adiacenti e "gatto". Ad esempio, questa query corrisponde a "Ho un cane grande e un gatto piccolo", ma non corrisponde a "Ho un grande cane e un grande gatto".
cat|dog È lo stesso che gatto OPPURE cane.
and OR or Corrisponde ai documenti che contengono il termine "and" o il termine "or" (l'operatore OR deve essere in maiuscolo)

Modalità di query avanzata

Oltre a una ricerca a testo intero puramente basata su token, Spanner supporta una modalità più completa chiamata enhance_query. Se attivata, questa modalità si estende la query di ricerca per includere altre varianti dei token. Queste riscritture aumentano le ricerche richiamo.

Per abilitare questa opzione, imposta l'argomento facoltativo enhance_query=>true nel Funzione SEARCH. Ad esempio, la query di ricerca hotl cal corrisponde all'album Hotel California.

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

La modalità enhance_query è un'opzione tempo query. Questa operazione non influisce sulla tokenizzazione. Puoi utilizzare lo stesso indice di ricerca con o senza enhance_query.

Google migliora continuamente gli algoritmi di miglioramento delle query. Di conseguenza, una query con enhance_query == true potrebbe produrre risultati leggermente diversi nel tempo.

Quando la modalità enhance_query è attiva, il numero di termini potrebbe aumentare cercata dalla funzione SEARCH e che potrebbe generare un aumento leggermente una latenza di pochi millisecondi.

Ad esempio, la seguente query utilizza un timeout di tre secondi e non va a buon fine se enhance_query non è disponibile:

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

Requisiti delle query SQL

Una query SQL deve soddisfare diverse condizioni per utilizzare un indice di ricerca. Se queste condizioni non sono soddisfatte, la query utilizza un piano di query alternativo o non va a buon fine se non esiste un piano alternativo.

Le query devono soddisfare le seguenti condizioni:

  • Le funzioni SEARCH e SEARCH_SUBSTRING richiedono un indice di ricerca. Spanner non supporta queste funzioni nelle query contro la tabella di base o gli indici secondari. Query relative a
  • Gli indici partizionati devono avere tutte le colonne di partizione vincolate da una condizione di uguaglianza nella clausola WHERE della query.

    Ad esempio, se un indice di ricerca è definito come PARTITION BY x, y, la query deve avere una congiuntiva nella clausola WHERE di x = <parameter or constant> AND y = <parameter or constant>. L'indice di ricerca non è considerato dallo strumento di ottimizzazione delle query se questa condizione è mancante.

  • Tutte le colonne TOKENLIST a cui fanno riferimento SEARCH e SEARCH_SUBSTRING gli operatori devono essere indicizzati nello stesso indice di ricerca.

    Ad esempio, considera la seguente definizione di tabella e indice:

    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 seguente query non va a buon fine perché non esiste un singolo indice di ricerca che indicizzi sia AlbumTitle_Tokens sia AlbumStudio_Tokens:

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
    
  • Se la colonna di ordinamento è con valore null, sia lo schema sia la query devono escludi le righe in cui la colonna di ordinamento è NULL. Consulta Ordinamento dell'indice di ricerca per maggiori dettagli.

  • Se l'indice di ricerca è filtrato per NULL, la query deve includere lo stesso Espressione di filtro NULL utilizzata in un indice. Per maggiori dettagli, consulta la sezione Indici di ricerca con filtro NULL.

  • Gli indici di ricerca non sono supportati in DML, in DML partizionati e partizionati query .

  • Gli indici di ricerca vengono generalmente utilizzati transazioni di sola lettura. Se i requisiti dell'applicazione consentono risultati inattivi, consigliamo di eseguire con una durata di inattività di almeno 10 secondi. Per ulteriori informazioni le informazioni, vedi Lettura di dati inattivi. Ciò è particolarmente utile per query di ricerca di grandi dimensioni che si espandono a più gruppi Paxos.

    Gli indici di ricerca non sono consigliati in transazioni di lettura/scrittura. Durante l'esecuzione, le query di ricerca bloccano un'intera partizione dell'indice. come un risultato, un'elevata percentuale di query di ricerca nelle transazioni di lettura/scrittura potrebbe conflitti di blocco che portano a picchi di latenza. Per impostazione predefinita, gli indici di ricerca selezionate automaticamente nelle transazioni di lettura/scrittura. Se una query viene forzata utilizza un indice di ricerca in una transazione di lettura/scrittura non riuscita per impostazione predefinita. Questo comportamento può essere ignorato con il suggerimento a livello di dichiarazione @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE} (ma le query sono comunque soggette a conflitti di blocco).

Una volta soddisfatte le condizioni di idoneità dell'indice, lo strumento di ottimizzazione delle query accelerare condizioni di query non testuali (come Rating > 4). Se l'indice di ricerca non include la colonna TOKENLIST appropriata, la condizione non è ha un'accelerazione e rimane una condizione residua.

Parametri di query

rquery e altri parametri come OFFSET sono specificati come valore letterale un parametro di query. Ti consigliamo di utilizzare parametri di ricerca anziché valori letterali stringa. Le query parametrizzate hanno tassi di hit della cache delle query migliori, il che si traduce in una latenza delle query inferiore e in un utilizzo complessivo della CPU inferiore.

Ad esempio, invece di utilizzare una query come la seguente:

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

utilizza la seguente sintassi:

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

Spanner esegue l'ottimizzatore delle query su testo SQL distinto. Minore è il numero di testi SQL distinti utilizzati dall'applicazione, minore è il numero di volte viene richiamata.

Ordinamento dell'indice di ricerca

Il comportamento dell'ordinamento degli indici di ricerca è diverso da quello secondario indici.

Ad esempio, considera la seguente tabella:

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'applicazione potrebbe definire un indice secondario per la ricerca di informazioni utilizzando AlbumName ordinati per ReleaseTimestamp:

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

L'indice di ricerca equivalente è il seguente (utilizza la tokenizzazione con corrispondenza esatta, poiché gli indici secondari non supportano le ricerche full-text):

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

L'ordinamento dell'indice di ricerca deve essere conforme alle seguenti regole:

  1. Utilizza le colonne INT64 solo per l'ordine di ordinamento di un indice di ricerca. Le colonne con dimensioni arbitrarie utilizzano troppe risorse nell'indice di ricerca perché Spanner deve memorizzare il docid accanto a ogni token. In particolare, la colonna di ordinamento non può utilizzare il tipo TIMESTAMP perché TIMESTAMP usa la precisione in nanosecondi, non rientra in un numero intero a 64 bit.
  2. Le colonne dell'ordine di ordinamento non devono essere NULL. Esistono due modi per soddisfare questo requisito:

    1. Dichiara la colonna dell'ordinamento come NOT NULL.
    2. Configura l'indice per escludere i valori NULL.

In pratica, per determinare l'ordinamento viene spesso utilizzato un timestamp. Un comune è quella di utilizzare microsecondi poiché lo standard Unix epoch per questi timestamp.

In genere le applicazioni recuperano per primi i dati più recenti utilizzando un indice di ricerca in ordine decrescente.

Selezione indice

In genere, Spanner seleziona l'indice più efficiente per una query utilizzando la modellazione basata sui costi. Tuttavia, il suggerimento FORCE_INDEX indica esplicitamente Spanner per usare un indice di ricerca specifico. Ad esempio, seguente mostra come forzare Spanner a utilizzare AlbumsIndex:

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

Se l'indice di ricerca specificato non è idoneo, non va a buon fine, anche se sono presenti altri indici di ricerca idonei.

Snippet nei risultati di ricerca

Uno snippet è un testo estratto da una determinata stringa che offre agli utenti un di cosa contiene un risultato di ricerca e perché il risultato è pertinenti alla loro query.

Ad esempio, Gmail utilizza gli snippet per indicare la parte di un'email che corrisponde alla query di ricerca:

Elenco di snippet

Fare in modo che il database generi uno snippet presenta diversi vantaggi:

  1. Comodità: non è necessario implementare la logica per generare snippet da una query di ricerca.
  2. Efficienza: gli snippet riducono le dimensioni dell'output dal server.

La funzione SNIPPET crea lo snippet. Restituisce la parte pertinente di il valore della stringa originale insieme alle posizioni dei caratteri da evidenziare. La Il cliente può scegliere in che modo mostrare lo snippet all'utente finale (ad esempio, utilizzando il testo evidenziato o in grassetto). La funzione SNIPPET rimuove tutti i tag HTML dalla stringa originale.

Ad esempio, nel seguente modo viene utilizzato SNIPPET per recuperare testo da AlbumTitle:

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

Passaggi successivi