【问题标题】:PostgreSQL: Returning ordered rows after a specific IDPostgreSQL:在特定 ID 之后返回有序行
【发布时间】:2018-06-26 12:03:38
【问题描述】:

场景: 我正在显示一个记录表。它最初显示前 500 个,底部带有“显示更多”,然后返回下一个 500。

问题: 如果在初始显示和单击“显示更多”之间添加了 1 条记录,这将导致“按日期排序,偏移 500,限制 500”重叠 1 行。

我想“按日期排序,偏移到‘显示的最后一行的 ID’,限制为 500”

我的行 ID 是 UUID。我对实现相同结果的替代方法持开放态度。

【问题讨论】:

  • @Lashane 为什么向期望唯一数据的用户显示重复数据是个问题?
  • 是的,为什么会出现问题?它是多用户环境,所以用户应该看到其他人的所有更新
  • 假设限制为 5 并且在按下显示更多之前添加了 1 行,用户将看到“A、B、C、D、E、E、F、G、H、I”双 E。随着更新速度的提高或限制的减小,效果会变得更差。
  • 我理解效果,你为什么认为它是问题?
  • 如果您必须订购的唯一列是日期,那么即使表格没有更改,分页也会出错。

标签: postgresql


【解决方案1】:

如果您可以按ID订购,则可以使用分页

where id > $last_seen_id limit 500

但这在您按date 排序的情况下没有用。

排序稳定!

我真的希望“日期”实际上意味着“时间戳”,否则您的排序将不稳定并且您可能会错过分页中的行;如果它真的是date,您必须通过date, id 订购才能获得稳定的订购,即使timestamp 也应该这样做。

客户端状态

一种选择是将状态推送给客户端。让客户端记住上次看到的 (date,id) 元组,并使用:

where date > $last_seen_date and id > $last_seen_id limit 500

光标

您关心可扩展性吗?如果没有,您可以使用服务器端游标。声明完整查询的游标,不带LIMIT。然后 FETCH 请求的行块。但是,要做到这一点,您的应用程序必须能够始终将连接绑定到特定用户的请求,而不是在请求之间重置该连接或将其返回到池中。这对于您的池/框架可能不实用,但如果可以的话,这可能是最好的解决方案。

临时表

另一个更不可扩展的选项是 CREATE TABLE sessiondata.myuser_myrequest_blah AS SELECT .... 然后对 那个 表进行分页。保证不会改变。这避免了需要在请求之间保持一致连接的困难,但第一次请求的响应时间会很慢,并且对于大量用户或大量数据是完全不切实际的。

相关问题

【讨论】:

    【解决方案2】:

    我认为您可以在 where 中使用子查询来完成此操作。

    例如假设您正在通过 users 表进行分页,并且您想要给定用户之后的记录:

    SELECT *
      FROM users
      WHERE created_at > (
        SELECT created_at
          FROM users
          WHERE users.id = '00000000-1111-2222-3333-444444444444'
          LIMIT 1
      )
      ORDER BY created_at DESC limit 5;
    

    【讨论】:

    • 如果日期不是唯一的则不起作用,这可能发生在批量插入的情况下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 2015-11-17
    • 2021-12-31
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多