Las aplicaciones web suelen paginar los datos a medida que se presentan a los usuarios. El usuario final recibe una página de resultados y, cuando accede a la página siguiente, se recupera y se muestra el siguiente lote de resultados. En esta página se describe cómo añadir paginación a los resultados de búsqueda al realizar una búsqueda de texto completo en Spanner.
Opciones de paginación
Hay dos formas de implementar consultas paginadas en Spanner: paginación basada en claves (recomendada) y paginación basada en desplazamientos.
La paginación basada en claves es un método para obtener resultados de búsqueda en fragmentos más pequeños y fáciles de gestionar, al tiempo que se asegura la coherencia de los resultados en las solicitudes. Se usa un identificador único (la "clave") del último resultado de una página como punto de referencia para obtener el siguiente conjunto de resultados.
Por lo general, Spanner recomienda usar la paginación basada en claves. Aunque la paginación basada en el desplazamiento es más fácil de implementar, tiene dos inconvenientes importantes:
- Mayor coste de las consultas: la paginación basada en el desplazamiento recupera y descarta repetidamente los mismos resultados, lo que aumenta los costes y reduce el rendimiento.
- Resultados incoherentes: en las consultas paginadas, cada página se suele recuperar con una marca de tiempo de lectura diferente. Por ejemplo, la primera página puede proceder de una consulta a las 13:00 y la siguiente, de una consulta a las 13:10. Esto significa que los resultados de búsqueda pueden cambiar entre consultas, lo que provoca resultados incoherentes en las páginas.
Por otro lado, la paginación basada en claves usa un identificador único (clave) del último resultado de una página para obtener el siguiente conjunto de resultados. De esta forma, se garantiza tanto una recuperación eficiente como resultados coherentes, incluso si cambian los datos subyacentes.
Para ofrecer estabilidad en los resultados de las páginas, la aplicación podría emitir todas las consultas de diferentes páginas en la misma marca de tiempo. Sin embargo, esto podría fallar si la consulta supera el periodo de conservación de versiones (el valor predeterminado es 1 hora). Por ejemplo, este error se produce si version_gc
es de una hora y el usuario final ha obtenido los primeros resultados a las 13:00 y ha hecho clic en Siguiente a las 15:00.
Usar la paginación basada en claves
La paginación basada en claves recuerda el último elemento de la página anterior y lo usa como punto de partida para la consulta de la página siguiente. Para ello, la consulta debe devolver las columnas especificadas en la cláusula ORDER BY
y limitar el número de filas mediante LIMIT
.
Para que la paginación basada en claves funcione, la consulta debe ordenar los resultados según un orden total estricto. La forma más sencilla de obtener una es elegir cualquier total de pedidos y, a continuación, añadir columnas de desempate si es necesario. En la mayoría de los casos, el orden total es el orden de clasificación del índice de búsqueda y la combinación única de columnas es la clave principal de la tabla base.
Si usamos nuestro esquema de ejemplo Albums
, la consulta de la primera página sería la siguiente:
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;
El AlbumId
es el factor de desempate, ya que ReleaseTimestamp
no es una clave. Puede que haya dos álbumes diferentes con el mismo valor de ReleaseTimestamp
.
Para reanudar la consulta, la aplicación vuelve a ejecutar la misma consulta, pero con una cláusula WHERE
que restringe los resultados de la página anterior. La condición adicional debe tener en cuenta la dirección de la clave (ascendente o descendente), los criterios de desempate y el orden de los valores NULL de las columnas que admiten valores NULL.
En nuestro ejemplo, AlbumId
es la única columna de clave (en orden ascendente) y no puede ser NULL, por lo que la condición es la siguiente:
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
En este ejemplo se usan los parámetros de consulta $1
, $2
, $3
y $4
, que están vinculados a los valores especificados para last_page_release_timestamp
, last_page_album_id
, query
y page_size
, respectivamente.
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 interpreta este tipo de condición como buscable. Esto significa que Spanner no lee el índice de los documentos que estás filtrando. Esta optimización es lo que hace que la paginación basada en claves sea mucho más eficiente que la paginación basada en desplazamientos.
Usar la paginación basada en el desplazamiento
La paginación basada en el desplazamiento aprovecha las cláusulas LIMIT
y OFFSET
de la consulta de SQL para simular páginas. El valor LIMIT
indica el número de resultados por página.
El valor de OFFSET
se establece en cero para la primera página, en el tamaño de la página para la segunda y en el doble del tamaño de la página para la tercera.
Por ejemplo, la siguiente consulta obtiene la tercera página, con un tamaño de página 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;
Notas de uso:
- Se recomienda encarecidamente usar la cláusula
ORDER BY
para asegurar que el orden sea coherente entre las páginas. - En las consultas de producción, use parámetros de consulta en lugar de constantes para especificar
LIMIT
yOFFSET
, de modo que el almacenamiento en caché de las consultas sea más eficiente. Para obtener más información, consulta Parámetros de consulta.
Siguientes pasos
- Consulta cómo clasificar los resultados de búsqueda.
- Consulte cómo realizar una búsqueda de subcadenas.
- Consulta cómo combinar consultas de texto completo y consultas que no son de texto.
- Consulta cómo buscar en varias columnas.