AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 338042
Accepted
odyssey
odyssey
Asked: 2024-03-26 03:09:07 +0800 CST2024-03-26 03:09:07 +0800 CST 2024-03-26 03:09:07 +0800 CST

Paginação eficiente no Postgresql (paginação de conjunto de chaves)

  • 772

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.

postgresql
  • 1 1 respostas
  • 41 Views

1 respostas

  • Voted
  1. Best Answer
    Charlieface
    2024-03-26T06:13:51+08:002024-03-26T06:13:51+08:00

    Existem três coisas principais que você precisa para poder usar a paginação do conjunto de chaves com sucesso.

    • Um ORDER BYem um conjunto exclusivo de colunas.
    • Nas páginas subsequentes, uma WHEREcláusula no mesmo conjunto de colunas, especificando >na mesma ordem.
    • Um índice nessas colunas com as colunas na mesma ordem, crescente ou decrescente.

    Sua consulta não parece fazer isso. Em primeiro lugar, você não está usando um conjunto exclusivo de colunas. Você precisaria adicionar userIdprovavelmente, 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 usar LOWERe, em seguida, um índice `(userForename, userCreatedAt, userId)

    SELECT
      userId,
      userForename,
      userCreatedAt
    FROM iatropolis."User"
    WHERE
        userForename > 'aaliyah'
        OR (userForename = 'aaliyah' AND
         userCreatedAt > TIMESTAMP '2024-03-25 14:50:39.481197')
        OR (userForename = 'aaliyah' AND
         userCreatedAt = TIMESTAMP '2024-03-25 14:50:39.481197' AND
         userId > '38ee48f9-6d79-5690-9e51-df4b1cc5d428')
    ORDER BY
      userForename ASC,
      userCreatedAt ASC,
      userId ASC
    LIMIT 10;
    

    Observe que no Postgres e em muitos outros SGBDs você pode apenas usar um row-comparator .

    SELECT
      userId,
      userForename,
      userCreatedAt
    FROM iatropolis."User"
    WHERE
        (userForename, userForename, userId) >
        ('aaliyah', TIMESTAMP '2024-03-25 14:50:39.481197', '38ee48f9-6d79-5690-9e51-df4b1cc5d428')
    ORDER BY
      userForename ASC,
      userCreatedAt ASC,
      userId ASC
    LIMIT 10;
    

    Para a página anterior, basta alterar ASCpara DESCe >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.

    • 1

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve