Les applications Web paginent souvent les données lorsqu'elles sont présentées aux utilisateurs. L'utilisateur final reçoit une page de résultats, et lorsqu'il accède à la page suivante, le lot de résultats suivant est récupéré et présenté. Cette page explique comment ajouter une pagination aux résultats de recherche lorsque vous effectuez une recherche en texte intégral dans Spanner.
Options de pagination
Il existe deux façons d'implémenter des requêtes paginées dans Spanner: la pagination basée sur une clé (recommandée) et la pagination basée sur un décalage.
La pagination basée sur une clé est une méthode permettant de récupérer des résultats de recherche en blocs plus petits et plus faciles à gérer, tout en garantissant des résultats cohérents entre les requêtes. Un identifiant unique (la "clé") du dernier résultat d'une page est utilisé comme point de référence pour récupérer l'ensemble de résultats suivant.
Spanner recommande généralement d'utiliser la pagination basée sur une clé. Bien que la pagination basée sur un décalage soit plus facile à implémenter, elle présente deux inconvénients majeurs :
- Coût de requête plus élevé : la pagination basée sur un décalage récupère et ignore de manière répétée les mêmes résultats, ce qui entraîne une augmentation des coûts et une baisse des performances.
- Résultats incohérents : dans les requêtes paginées, chaque page est généralement récupérée à un horodatage de lecture différent. Par exemple, la première page peut provenir d'une requête à 13h et la suivante d'une requête à 13h10. Cela signifie que les résultats de recherche peuvent changer entre les requêtes, ce qui entraîne des résultats incohérents sur les pages.
La pagination basée sur une clé, en revanche, utilise un identifiant unique (clé) du dernier résultat d'une page pour récupérer l'ensemble de résultats suivant. Cela garantit à la fois une récupération efficace et des résultats cohérents, même si les données sous-jacentes changent.
Pour assurer la stabilité des résultats de la page, l'application peut émettre toutes les requêtes pour différentes pages au même horodatage. Toutefois, cela peut échouer si la
requête dépasse la période de conservation des versions
(la valeur par défaut est de 1 heure). Par exemple, cet échec se produit si version_gc est d'une heure, et que l'utilisateur final a récupéré les premiers résultats à 13h et cliqué sur Suivant à 15h.
Utiliser la pagination basée sur une clé
La pagination basée sur une clé mémorise le dernier élément de la page précédente et l'utilise comme point de départ pour la requête de la page suivante. Pour ce faire, la requête doit renvoyer les colonnes spécifiées dans la clause ORDER BY et limiter le nombre de lignes à l'aide de LIMIT.
Pour que la pagination basée sur une clé fonctionne, la requête doit trier les résultats selon un ordre total strict. Le moyen le plus simple d'en obtenir un consiste à choisir un ordre total total, puis à ajouter des colonnes de départage de départage, si nécessaire. Dans la plupart des cas, l'ordre total correspond à l'ordre de tri de l'index de recherche, et la combinaison unique de colonnes correspond à la clé primaire de la table de base.
En utilisant notre exemple de schéma Albums, pour la première page, la requête se présente comme suit :
GoogleSQL
SELECT AlbumId, ReleaseTimestamp
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY ReleaseTimestamp DESC, AlbumId
LIMIT 10;
PostgreSQL
SELECT albumid, releasetimestamp
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY releasetimestamp DESC, albumid
LIMIT 10;
AlbumId est le départage, car ReleaseTimestamp n'est pas une clé. Il peut y avoir deux albums différents avec la même valeur pour ReleaseTimestamp.
Pour reprendre, l'application exécute à nouveau la même requête, mais avec une clause WHERE qui limite les résultats de la page précédente. La condition supplémentaire doit tenir compte du sens de la clé (ascendant ou descendant), des départages et de l'ordre des valeurs NULL pour les colonnes acceptant les valeurs NULL.
Dans notre exemple, AlbumId est la seule colonne de clé (par ordre croissant) et ne peut pas être NULL. La condition est donc la suivante :
GoogleSQL
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;
PostgreSQL
Cet exemple utilise les paramètres de requête $1, $2, $3 et $4, qui sont liés aux valeurs spécifiées pour last_page_release_timestamp, last_page_album_id, query et page_size, respectivement.
SELECT albumid, releasetimestamp
FROM albums
WHERE (releasetimestamp < $1
OR (releasetimestamp = $1
AND albumid > $2))
AND spanner.search(albumtitle_tokens, $3)
ORDER BY releasetimestamp DESC, albumid ASC
LIMIT $4;
Spanner interprète ce type de condition comme pouvant être recherché. Cela signifie que Spanner ne lit pas l'index des documents que vous filtrez. Cette optimisation rend la pagination basée sur une clé beaucoup plus efficace que la pagination basée sur un décalage.
Utiliser la pagination basée sur un décalage
La pagination basée sur un décalage exploite les clauses LIMIT et OFFSET de la requête SQL pour simuler des pages. La valeur LIMIT indique le nombre de résultats par page.
La valeur OFFSET est définie sur zéro pour la première page, sur la taille de la page pour la deuxième page et sur le double de la taille de la page pour la troisième page.
Par exemple, la requête suivante récupère la troisième page, avec une taille de page de 50 :
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY ReleaseTimestamp DESC, AlbumId
LIMIT 50 OFFSET 100;
PostgreSQL
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY releasetimestamp DESC, albumid
LIMIT 50 OFFSET 100;
Remarques sur l'utilisation :
- La clause
ORDER BYest fortement recommandée pour garantir un ordre cohérent entre les pages. - Dans les requêtes de production, utilisez des paramètres de requête plutôt que des constantes pour spécifier
LIMITetOFFSETafin de rendre la mise en cache des requêtes plus efficace. Pour plus d'informations, consultez la section Paramètres de requête.
Étape suivante
- Découvrez comment classer les résultats de recherche.
- Découvrez comment effectuer une recherche de sous-chaîne.
- Découvrez comment combiner des requêtes en texte intégral et des requêtes non textuelles.
- Découvrez comment effectuer une recherche dans plusieurs colonnes.