数据库中结果的分页如何工作?

How does pagination of results in databases work?

这是一个适用于 MySQL、Oracle DB 或其他任何可能存在的问题的一般性问题。

我知道 MySQL 有 LIMIT 偏移量,大小;对于 Oracle,有 'ROW_NUMBER' 或类似的东西。

但是,当这样的 'paginated' 查询被接连调用时,数据库引擎实际上是否会重新执行整个 'select',然后每次都检索不同的结果子集?或者它是否只对结果进行一次整体提取,将结果保存在内存或其他东西中,然后根据偏移量和大小为后续查询提供结果的子集?

如果每次都full fetch的话,效率似乎很低。

如果它只进行一次完全获取,那一定是 'storing' 某个地方的查询,这样下次查询进来时,它就知道它已经获取了所有数据,只需要从中提取下一页。 在那种情况下,数据库引擎将如何处理多线程?两个线程执行同一个查询?

我很困惑:(

是的,当您 运行 使用不同的偏移量时,查询会再次执行。

是的,这是低效的。如果您需要对大型结果集进行分页,请不要这样做。

我建议使用较大的 LIMIT 进行一次查询 — 足够 10 或 12 页。然后将结果保存在缓存中。当用户想要浏览多个页面时,您的应用程序可以获取您保存在缓存中的 10-12 个页面并显示用户想要查看的页面。这通常比 运行 对每个页面执行 SQL 查询要快得多。

如果像大多数用户一样,您的用户只阅读了几页然后更改他们的查询,则此方法很有效。


回复您的评论:

我所说的缓存是指 Memcached 或 Redis 之类的东西。高速内存 key/value 存储。

MySQL 视图不存储任何内容,它们更像是一个宏,运行 是为您预定义的查询。

Oracle 支持物化视图,因此可能会更好,但查询视图会产生解释 SQL 查询的开销。

更简单的内存缓存应该更快。

我不同意@Bill Karwin。首先,不要在没有测量的情况下就预先假设某件事是快还是慢,并且提前将代码复杂化以一次下载12个页面并缓存它们,因为"it seems to me that it will be faster"。

YAGNI principle - 除非认为有必要,否则程序员不应添加功能。
用最简单的方式来做(普通的一页分页),量产上效果如何,慢了就换个方法,速度满意就保持原样。


根据我自己的实践 - 一个从包含大约 80,000 条记录的 table 中检索数据的应用程序,主 table 与 4-5 个额外的查找 table 相结合,整个查询是分页的,每页约25-30条记录,总共约2500-3000页。数据库是Oracle 12c,少数列有索引,查询由Hibernate生成。 服务器端对生产系统的测量表明,检索一页的平均时间(中位数 - 50% 百分位数)约为 300 毫秒。 95% 的百分位数小于 800 毫秒——这意味着 95% 的检索单个页面的请求小于 800 毫秒,当我们添加从服务器到用户的传输时间和大约 0.5-1 秒的呈现时间时,总时间少于 2 秒。够了,用户开心


和一些理论 - 查看此答案以了解

的目的是什么