有没有办法用 pgpromse 查看限制偏移查询是不是已经结束?

Posted

技术标签:

【中文标题】有没有办法用 pgpromse 查看限制偏移查询是不是已经结束?【英文标题】:Is there a way to see if a limit offset query has reached the end with pgpromse?有没有办法用 pgpromse 查看限制偏移查询是否已经结束? 【发布时间】:2021-10-31 17:56:30 【问题描述】:

我有一个帖子表。我想将这些帖子查询为页面。因为我想让我的端点保持无状态,所以我想用这样的偏移量和限制来做到这一点:

SELECT * FROM post LIMIT 50 OFFSET $1 ORDER BY id

其中 1 美元是页码乘以页面大小 (50)。检查我们是否已经结束的简单方法是查看我们是否返回了 50 页。当然,问题是页数是否能被 50 整除,我们无法确定。 到目前为止,我解决这个问题的方法是简单地为每个查询获取 51 个帖子,页面大小仍然为 50。这样,如果返回查询小于 51,我们就已经结束了。

不幸的是,这似乎是一种非常老套的方法。所以我想知道,pg-promise 或 postgresql 中是否有一些功能可以表明我已经到达表的末尾而不诉诸这样的技巧?

【问题讨论】:

短版 - 不,Postgres 中没有这样的“功能”,您必须再次重新请求数据以查看是否有剩余。而且,pg-promise 在这里不相关。 【参考方案1】:

没有直接用于此的内置过程。但是您可以计算行数并将其添加到结果中。然后,您甚至可以为用户提供项目数或页数:

-- Item count
with pc(cnt) as (select  count(*)  from post)   
select p.*, cnt 
  from post p 
  cross join pc
 limit 50 offset $1; 

 -- page count
with pc(cnt) as (select  count(*)/50 + ((count(*)%50)>0)::int  from post)   
select p.*, cnt 
  from post p 
  cross join pc
 limit 50 offset $1; 

注意:计数功能可能很慢,即使不是,它也会增加响应时间。是否值得额外的开销?只有您和用户才能回答这个问题。

【讨论】:

子查询可能比 CTE 和交叉连接更简单。 也许,我认为它更像是风格选择。但我可能会同时测试两者。 我认为我的解决方案会坚持下去,因为我不需要在每次迭代中计算所有行并且完成基本相同的用途。还是谢谢【参考方案2】:

我发现的开销最低的最简单方法:

您可以在每个页面请求上请求 pageLimit+1 行。在您的控制器中,您将检查是否有rowsCount > pageLimit 并知道有更多可用数据。当然,在返回行之前,您需要删除最后一个元素并沿行发送类似 hasNext 布尔值的内容。

数据库检索额外的数据行通常比计算所有行数或额外请求page+1 以检查它是否返回任何行要便宜得多。

【讨论】:

是的,我就是这样做的【参考方案3】:

此方法仅在特定设置中有效(SPA 缓存网络请求并希望通过预取使分页感觉更快):

每页一个,您发出两个请求:一个用于当前页面数据,一个用于下一页数据。

例如,如果您使用带有 react-query 的 React 单页应用程序,其中 nextPage 不会被重新获取,而是在用户打开它时重用。

否则,如果 nextPage 没有被重用,这比检查总行数来确定是否还有剩余行更糟糕,因为您将为每个页面发出 2 个请求。

它甚至可以使用户界面更快捷,因为到下一页的转换总是即时的。

如果您有很多页面转换,因为调用的总数等于 numberOfPages+1,这种方法会很有效,所以如果平均用户访问 10 个页面,numberOfPages+1=10+1 或只有 10% 的开销。但是,如果您的用户通常不会超出第一页,则没有什么意义,因为在这种情况下 numberOfPages+1=2 会调用单个页面。

【讨论】:

以上是关于有没有办法用 pgpromse 查看限制偏移查询是不是已经结束?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 偏移无限行

这是不是可以获得具有偏移限制的总行数

解决 pyopencl 数组偏移限制

有没有办法用内容偏移量初始化 UICollectionView?

具有限制和偏移量的 CodeIgniter sql 查询未显示结果

在数据库查询中获取行时使用 PHP 限制结果,而不使用 LIMIT 子句?