Os aplicativos da Web geralmente paginam os dados à medida que são apresentados aos usuários. O usuário final recebe uma página de resultados e, quando navega para a próxima página, o próximo lote de resultados é recuperado e apresentado. Esta página descreve como adicionar paginação aos resultados da pesquisa ao realizar uma pesquisa de texto completo no Spanner.
Opções de paginação
Há duas maneiras de implementar consultas paginadas no Spanner: paginação baseada em chave (recomendada) e paginação baseada em deslocamento.
A paginação baseada em chave é um método para recuperar resultados da pesquisa em blocos menores e mais gerenciáveis, garantindo resultados consistentes em todas as solicitações. Um identificador exclusivo (a "chave") do último resultado de uma página é usado como um ponto de referência para buscar o próximo conjunto de resultados.
O Spanner geralmente recomenda o uso da paginação baseada em chave. Embora a paginação baseada em deslocamento seja mais fácil de implementar, ela tem duas desvantagens significativas:
- Custo de consulta mais alto:a paginação baseada em deslocamento recupera e descarta repetidamente os mesmos resultados, levando a custos maiores e desempenho reduzido.
- Resultados inconsistentes:em consultas paginadas, cada página é normalmente recuperada em um carimbo de data/hora de leitura diferente. Por exemplo, a primeira página pode vir de uma consulta às 13h e a próxima de uma consulta às 13h10. Isso significa que os resultados da pesquisa podem mudar entre as consultas, levando a resultados inconsistentes em todas as páginas.
A paginação baseada em chave, por outro lado, usa um identificador exclusivo (chave) do último resultado de uma página para buscar o próximo conjunto de resultados. Isso garante uma recuperação eficiente e resultados consistentes, mesmo que os dados subjacentes mudem.
Para oferecer estabilidade nos resultados da página, o aplicativo pode emitir todas as consultas para páginas diferentes no mesmo carimbo de data/hora. No entanto, isso poderá falhar se a
consulta exceder o período de retenção da versão
(o padrão é de 1 hora). Por exemplo, essa falha acontece se version_gc for de uma hora e o usuário final buscar os primeiros resultados às 13h e clicar em Próximo às 15h.
Usar a paginação baseada em chave
A paginação baseada em chave lembra o último item da página anterior e o usa como ponto de partida para a próxima consulta de página. Para isso, a consulta precisa retornar as colunas especificadas na cláusula ORDER BY e limitar o número de linhas usando LIMIT.
Para que a paginação baseada em chave funcione, a consulta precisa ordenar os resultados por alguma ordem total estrita. A maneira mais fácil de conseguir uma é escolher qualquer ordem total e adicionar colunas de desempate, se necessário. Na maioria dos casos, a ordem total é a ordem de classificação do índice de pesquisa e a combinação exclusiva de colunas é a chave primária da tabela base.
Usando nosso esquema de amostra Albums, para a primeira página, a consulta é semelhante a esta:
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;
O AlbumId é o desempate, já que ReleaseTimestamp não é uma chave. Pode haver dois álbuns diferentes com o mesmo valor para ReleaseTimestamp.
Para retomar, o aplicativo executa a mesma consulta novamente, mas com uma cláusula WHERE que restringe os resultados da página anterior. A condição adicional precisa considerar a direção da chave (ascendente versus descendente), os desempates e a ordem dos valores NULL para colunas anuláveis.
No nosso exemplo, AlbumId é a única coluna de chave (em ordem crescente) e não pode ser NULL. Portanto, a condição é a seguinte:
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
Este exemplo usa parâmetros de consulta $1, $2, $3 e $4, que estão vinculados aos valores especificados para last_page_release_timestamp, last_page_album_id, query e 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;
O Spanner interpreta esse tipo de condição como pesquisável. Isso significa que o Spanner não lê o índice de documentos que você está filtrando. Essa otimização é o que torna a paginação baseada em chave muito mais eficiente do que a paginação baseada em deslocamento.
Usar a paginação baseada em deslocamento
A paginação baseada em deslocamento aproveita as cláusulas LIMIT e OFFSET da consulta SQL para simular páginas. O valor LIMIT indica o número de resultados por página.
O valor OFFSET é definido como zero para a primeira página, o tamanho da página para a segunda página e o dobro do tamanho da página para a terceira página.
Por exemplo, a consulta a seguir busca a terceira página, com um tamanho 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;
Observações sobre o uso:
- A cláusula
ORDER BYé altamente recomendada para garantir uma ordem consistente entre as páginas. - Em consultas de produção, use parâmetros de consulta em vez de constantes para especificar
LIMITeOFFSETpara tornar o armazenamento em cache de consultas mais eficiente. Para mais informações, consulte Parâmetros de consulta.
A seguir
- Saiba como classificar os resultados da pesquisa.
- Saiba como realizar uma pesquisa de substrings.
- Saiba como misturar consultas de texto completo e não textuais.
- Saiba como pesquisar várias colunas.