Paginare i risultati di ricerca

Le applicazioni web spesso impaginano i dati quando vengono presentati agli utenti. L'utente finale riceve una pagina di risultati e, quando passa alla pagina successiva, viene recuperato e presentato il successivo lotto di risultati. In questa pagina viene descritto come aggiungere l'impaginazione ai risultati di ricerca la ricerca a testo intero in Spanner.

Panoramica

Esistono due modi per implementare le query impaginate in Spanner: impaginazione basata su chiavi (consigliato) e impaginazione basata sull'offset.

L'impaginazione basata su chiave è un metodo per recuperare risultati di ricerca in modo più piccolo a blocchi gestibili garantendo al contempo risultati coerenti tra le richieste. Un identificatore unico (la "chiave") dell'ultimo risultato di una pagina viene utilizzato come punto di riferimento per recuperare il set di risultati successivo.

Spanner consiglia in genere di utilizzare l'impaginazione basata su chiave. Mentre l'impaginazione basata su offset è più facile da implementare, ha due drawbacks:

  1. Costo delle query più elevato: la paginazione basata su offset recupera e ignora ripetutamente gli stessi risultati, con un conseguente aumento dei costi e una diminuzione delle prestazioni.
  2. Risultati incoerenti: nelle query con paginazione, in genere ogni pagina viene recuperata con un timestamp di lettura diverso. Ad esempio, la prima pagina potrebbe provenire da una query alle 13:00 e la successiva da una query alle 13:10. Ciò significa i risultati di ricerca possono cambiare da una query all'altra, generando risultati su più pagine.

La paginazione basata su chiavi, invece, utilizza un identificatore univoco (chiave) dell'ultimo risultato di una pagina per recuperare l'insieme di risultati successivo. Questo assicura un recupero efficiente e risultati coerenti, anche se i dati sottostanti cambiano.

Per garantire la stabilità dei risultati della pagina, l'applicazione potrebbe emettere tutte le query per pagine diverse allo stesso timestamp. Tuttavia, l'operazione potrebbe non riuscire se la query supera la conservazione della versione punto (il valore predefinito è 1 ora). Ad esempio, questo errore si verifica se version_gc è equale a un'ora e l'utente finale ha recuperato i primi risultati alle 13:00 e ha fatto clic su Avanti alle 15:00.

Usa l'impaginazione basata su chiave

La paginazione basata su chiavi memorizza l'ultimo elemento della pagina precedente e lo utilizza come punto di partenza per la query della pagina successiva. Per farlo, la query deve restituire le colonne specificate nella clausola ORDER BY e limitare il numero di righe utilizzando LIMIT.

Affinché l'impaginazione basata su chiave funzioni, la query deve ordinare i risultati in base a una nell'ordine totale. Il modo più semplice per ottenerne uno è scegliere qualsiasi totale ordine e poi aggiungere lo spareggio colonne, se necessario. Nella maggior parte dei casi, l'ordine totale è l'ordine di ordinamento dell'indice di ricerca e la combinazione univoca di colonne è la chiave primaria della tabella di base.

Utilizzando il nostro schema di esempio Albums, per la prima pagina la query è la seguente:

SELECT AlbumId, ReleaseTimestamp
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "green")
ORDER BY ReleaseTimestamp DESC, AlbumId
LIMIT @page_size;

AlbumId è il tie-breaking: ReleaseTimestamp non è una chiave. Là potrebbe essere due album diversi con lo stesso valore per ReleaseTimestamp.

Per riprendere, l'applicazione esegue di nuovo la stessa query, ma con una clausola WHERE che limita i risultati della pagina precedente. La condizione aggiuntiva deve tenere conto della direzione delle chiavi (crescente o decrescente), dei tie-breaking e l'ordine dei valori NULL per le colonne con valori null.

Nel nostro esempio, AlbumId è l'unica colonna chiave (in ordine crescente) e non può essere NULL, quindi la condizione è la seguente:

SELECT AlbumId, ReleaseTimestamp
FROM Albums
WHERE (ReleaseTimestamp < @last_page_release_timestamp
       OR (ReleaseTimestamp = @last_page_release_timestamp
           AND AlbumId > @last_page_album_id))
      AND SEARCH(AlbumTitle_Tokens, @p)
ORDER BY ReleaseTimestamp DESC, AlbumId ASC
LIMIT @page_size;

Spanner interpreta questo tipo di condizione come seekable. Ciò significa che Spanner non legge l'indice dei documenti che stai escludendo. Questa ottimizzazione è ciò che rende molto più efficiente l'impaginazione basata su chiave rispetto all'impaginazione basata su offset.

Utilizza l'impaginazione basata su offset

L'impaginazione basata sull'offset sfrutta le clausole LIMIT e OFFSET della query SQL per simulare pagine. Il valore LIMIT indica il numero di risultati per pagina. Il valore OFFSET è impostato su zero per la prima pagina e su zero per la seconda e raddoppia le dimensioni della terza pagina.

Ad esempio, la seguente query recupera la terza pagina, con una dimensione di 50 pagine:

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "green")
ORDER BY ReleaseTimestamp DESC, AlbumId
LIMIT 50 OFFSET 100;

Note sull'utilizzo:

  • La clausola ORDER BY è vivamente consigliata per garantire un ordine coerente tra le pagine.
  • Nelle query di produzione, utilizza i parametri di query anziché le costanti per specificare LIMIT e OFFSET per rendere la memorizzazione nella cache delle query più efficiente. Per ulteriori informazioni, consulta la sezione Parametri di query.

Passaggi successivi