Estou trabalhando na implementação da paginação para um banco de dados PostgreSQL no qual tenho uma tabela que armazena usuários para meu aplicativo. Eu tenho uma consulta que visa buscar a próxima página de usuários com base em seu nome próprio e carimbo de data/hora de criação. No entanto, estou encontrando algumas dificuldades e gostaria de receber alguma orientação.
Tipos para as colunas: userId (string e armazena uuidv5), userForename (string), userCreatedAt (timestamp)
Aqui está a consulta que estou usando para buscar a próxima página: é apenas um espaço reservado
SELECT "userId", "userForename", "userCreatedAt"
FROM iatropolis."User"
WHERE
LOWER("userForename") > 'aaliyah'
OR (LOWER("userForename") = 'aaliyah' AND
"userCreatedAt" > TIMESTAMP '2024-03-25 14:50:39.481197')
ORDER BY "userForename" ASC, "userCreatedAt" ASC
LIMIT <limit>;
O objetivo desta consulta é recuperar o primeiro usuário após 'aaliyah' em ordem alfabética e, se houver vários usuários com o mesmo nome, selecionar aquele com carimbo de data e hora de criação posterior a '2024-03-25 14:50:39.481197' .
No entanto, não tenho certeza se esta consulta está atingindo corretamente a paginação desejada. Embora eu tenha testado e produzido resultados corretos, não sei se ele se comportará conforme desejado no longo prazo (não tenho certeza se estou faltando alguma coisa).
Também tentei ir para a página anterior comprar criando uma consulta semelhante.
SELECT "userId", "userForename", "userCreatedAt"
FROM iatropolis."User"
WHERE
LOWER("userForename") < 'zula'
OR (LOWER("userForename") = 'zula' AND
"userCreatedAt" < TIMESTAMP '2024-03-25 14:51:53.062856')
ORDER BY "userForename" DESC, "userCreatedAt" DESC
LIMIT <limit>;
Estes são alguns dados aleatórios ascendentes com os quais estou trabalhando:
ID do usuário | nome_do_usuário | userCreatedAt |
---|---|---|
38ee48f9-6d79-5690-9e51-df4b1cc5d428 | Aaliyah | 25/03/2024 14:50:39.481197 |
ba2c1a86-280d-573f-ad35-ed1d023e3e5d | Aaliyah | 25/03/2024 14:51:35.52505 |
4f40dd7a-8f0f-54e4-bf14-3de3626bde67 | Abagail | 25/03/2024 19:27:10.985665 |
e7b68316-188d-509e-9fd3-7fc780986c71 | Mosteiro | 25/03/2024 17:45:43.584704 |
1084f33e-9183-501d-b1af-70d61f1479d7 | Abigail | 25/03/2024 19:27:29.720356 |
561e71fd-f04a-54d2-9864-2324e28cdfbd | Abigail | 25/03/2024 19:27:35.5478 |
ab5ad018-1866-50a4-8bf6-568f74988d21 | Abigail | 25/03/2024 17:46:35.309003 |
596e13f2-e413-5b50-bdfb-9e68f0edf3db | Abdiel | 25/03/2024 17:47:08.576102 |
d0d5bff9-f782-5451-bda4-e4d4a3e49f04 | Abdiel | 25/03/2024 14:51:24.257638 |
33a02ded-b354-5a6b-b506-cad3595d19be | Abdul | 25/03/2024 17:46:49.809666 |
6e1f68ff-f799-511e-ba91-83b35349e652 | Abdul | 25/03/2024 14:51:02.533247 |
f67226da-a560-5913-9770-c23499046dc5 | Abe | 25/03/2024 14:49:34.342507 |
4e345a84-144d-55e2-a568-ce2064cb91fc | Abigale | 25/03/2024 19:26:32.349998 |
ecab4167-8275-5c45-a6ce-5f616edeb60b | Abigale | 25/03/2024 19:26:24.406462 |
3689dc88-b57c-572b-90cd-3bd0c4603656 | Abigayle | 25/03/2024 14:50:41.608976 |
db26cecb-0532-5cd4-b45e-04c14ce48b97 | Abigayle | 25/03/2024 19:26:54.081197 |
03d9e144-ba2e-5d08-b8bc-abaa42b59848 | Abner | 25/03/2024 17:47:12.313267 |
e7d3fd8b-9187-5e78-8178-93eef85c3edc | Abner | 25/03/2024 19:27:35.016205 |
3a0c5db0-a19b-57b2-be99-6c0e0d33fb4c | adadadFN | 22/03/2024 11:33:03.466138 |
daada509-45b3-58e8-920f-2441395af0f8 | Adalberto | 25/03/2024 17:46:31.150524 |
dd3781a8-45ae-5ecb-9d5d-b4230347b0d8 | Adalina | 25/03/2024 17:46:05.821796 |
c2122ddb-fd31-59ea-b5db-3e8696f0a2fc | Adán | 25/03/2024 14:51:06.880816 |
19ac3589-47ac-53ba-8e8c-c1537babbe97 | Adie | 25/03/2024 17:47:04.303399 |
c61c8d3a-02b7-5db3-8b84-dba2fbf522b8 | Adie | 25/03/2024 17:46:35.627732 |
6800cc09-113a-5383-a9ec-463bfeb1f3aa | Addison | 25/03/2024 17:46:24.314788 |
Estes são alguns dados aleatórios descendentes com os quais estou trabalhando:
ID do usuário | nome_do_usuário | userCreatedAt |
---|---|---|
d64ce86e-1bf4-56d8-86dc-e0ffd9bae972 | Zula | 25/03/2024 14:51:53.062856 |
e6f98b6c-ae16-58e9-ba3a-979dac63058d | Zora | 25/03/2024 17:46:15.697886 |
951b1493-0f86-5741-8b3d-5b7db7466f25 | Zora | 25/03/2024 14:51:38.315643 |
a2c4455e-5333-57ea-9e7e-6a8ca03a7cf4 | Zita | 25/03/2024 19:26:44.119388 |
d00c4951-de6a-5290-b956-13bf3b3e11eb | Zita | 25/03/2024 14:51:28.445206 |
390b6dae-b47e-57d7-8a7f-10a002d9b3a3 | Sião | 25/03/2024 14:50:18.578468 |
6f6371a0-b5bd-5839-aed2-81e8b8e0bff7 | Zeta | 25/03/2024 19:27:22.998847 |
4750df40-ffda-55e2-b26b-7c0c2ecf87e5 | Zeta | 25/03/2024 19:26:01.682206 |
14d137e7-83aa-5463-b47e-1a2376b53376 | Zelma | 25/03/2024 14:50:15.690687 |
0defcb46-486c-5273-9c81-e553500de614 | Zelma | 25/03/2024 14:49:32.577772 |
1a28a48b-bc3b-5f84-bbae-1ac0839bf311 | Zacarias | 25/03/2024 19:26:04.410123 |
574bf44e-2604-5ff1-95a9-164287d3c880 | Zane | 25/03/2024 19:27:15.455109 |
e7b0e413-2eff-5240-8c18-321664a42416 | Zander | 25/03/2024 19:26:45.864325 |
2a737734-2c45-54c0-b911-315c8d333884 | Zakary | 25/03/2024 14:50:34.264419 |
782ddfaa-df67-50e3-841d-fa21b525e75c | Zackery | 25/03/2024 17:47:17.542445 |
d24c75f2-7152-50aa-96ef-3a2d3847f1d3 | Zackary | 25/03/2024 17:46:58.029806 |
c2d6d8c5-3891-57fb-bbea-57e22cb51da4 | Zack | 25/03/2024 17:46:27.203011 |
3333d2de-8028-5f00-8e4c-db821e8fe1a5 | Zachary | 25/03/2024 17:46:25.890929 |
f11dfc68-78f1-5290-b203-9e04449c0538 | Zachary | 25/03/2024 14:50:27.447767 |
d88c05bc-5fe4-5597-94b5-ca29c99a2df4 | Zacarias | 25/03/2024 17:46:52.98815 |
cf8e2a99-e308-53ae-8908-8c2ff0188143 | Zacarias | 25/03/2024 14:51:47.465403 |
da1ed730-9965-56c2-9317-e1726f172afc | Ivone | 25/03/2024 19:26:36.714501 |
97a4213a-5fd5-5d0d-a860-567295ab9a23 | Ivone | 25/03/2024 14:51:20.7755 |
41ce8c6b-5cca-57b9-a74b-d9fbf8f32ade | Ivete | 25/03/2024 14:50:18.973821 |
9f47693b-bcfd-5e2c-b92f-56aefb79ce03 | Yoshiko | 25/03/2024 19:27:33.647082 |
Minha pergunta é: alguém que conhece SQL corretamente e o usa há anos e anos, concordaria que essa paginação de conjunto de chaves foi implementada corretamente? Além disso, para o meu caso, poder ordenar as colunas é muito importante, por isso incluí o userForename nas consultas. Caso minhas dúvidas não estejam corretas, alguém poderia me mostrar como fazê-las corretamente? Além disso, estou aberto a explorar abordagens alternativas se existirem soluções mais eficientes disponíveis.
Existem três coisas principais que você precisa para poder usar a paginação do conjunto de chaves com sucesso.
ORDER BY
em um conjunto exclusivo de colunas.WHERE
cláusula no mesmo conjunto de colunas, especificando>
na mesma ordem.Sua consulta não parece fazer isso. Em primeiro lugar, você não está usando um conjunto exclusivo de colunas. Você precisaria adicionar
userId
provavelmente, para garantir resultados determinísticos.Além disso, você precisa de um índice de suporte no mesmo conjunto de colunas; portanto, a menos que você tenha um índice ativado,
(LOWER(userForename), userCreatedAt, userId)
ele não terá desempenho. Eu aconselho apenas definir um agrupamento que não diferencia maiúsculas de minúsculas, em vez de usarLOWER
e, em seguida, um índice `(userForename, userCreatedAt, userId)Observe que no Postgres e em muitos outros SGBDs você pode apenas usar um row-comparator .
Para a página anterior, basta alterar
ASC
paraDESC
e>
para<
.Nota lateral: não prefixe cada coluna com o nome da tabela, sabemos de qual tabela ela vem. E não cite nomes de colunas, a menos que seja necessário, pois isso dificulta a leitura.