在 SQL 中,哪个更快:LIMIT ... OFFSET 还是范围查询?

oam*_*awi 2 mysql sql performance range limit

给定


例子

| name    | id |
|---------|----|
| Lynne   | 1  |
| Johnny  | 2  |
| D'Andra | 3  |
| Kimmel  | 4  |
|        ...   |
Run Code Online (Sandbox Code Playgroud)

客观的

获取 id 大于或等于 3 的 10 个人。


问题

select name from employees order by id limit 10 offset 3使用or会更快吗select name from employees where id >= 3 and id <13 order by id?为什么?


到目前为止我检查过的内容

当您知道只有 1 个结果时,向 MySQL 查询添加“LIMIT 1”是否会使查询速度更快?:这表示使用限制比不使用限制更快,但它并没有将其与范围查询进行比较。

带有偏移量限制的选择查询太慢:这表明偏移量通常很慢,因为它需要遍历所有行才能到达偏移量。它没有讨论它的使用是否offset xid >= x任何整数 x 慢?

Gor*_*off 6

你的两个查询不一样。仅当您知道该id列没有间隙且(并且没有重复项,但这对于 )时它们才是相同的id

对于小偏移量,这样一个简单的查询应该没有区别。不过,我确实认为 MySQL 将读取查询的所有结果offset,然后在达到偏移量时开始返回结果。也就是说,它实际上计算行数,然后输出偏移量之后的行。

where子句应该使 MySQL 直接转到索引中的正确记录。对于较大的结果集来说,这应该更快。


Ric*_*mes 5

也许这两者都不是最佳的。

在网页中常见的操作是“分页”,其中第一个“页面”显示“前”10 个项目,第二个页面显示接下来的 10 个项目,等等。

OFFSET当你越来越深入列表时,使用效率非常低——它必须小心翼翼地跨过每个“偏移”行,然后才能看到第 10 行。

如果idAUTOINCREMENT,则不能保证 ids 随着时间的推移是连续的。集群中的删除REPLACE、复制等可能会留下间隙。INSERT IGNORE当然,这个数字今天效果很好。但你不应该相信明天有人“修复”了数据中的某些内容。

分页的最佳方法是“记住你离开的地方”。没有OFFSET使用。 id(或其他一些唯一的列)只是一个占位符,而不是数字。

更多详细信息: http://mysql.rjweb.org/doc.php/pagination

OP的问题

使用 select name fromEmployees order by id limit 10 offset 3 或 select name fromEmployees where id >= 3 and id <13 order by id 会更快吗?为什么?

(让我修改数字以使答案更明显:)

  • limit 10 offset 300-- 处理必须达到 300 行才能达到所需的 10 行;共触及 310 行。
  • where id >= 300 and id < 310id-- 假设(可能是)上有一个索引PRIMARY KEY,则只需要触及 10 行。
  • 正如我在链接中指出的,这避免了一个未提及的问题:如果 id=305 的行被删除怎么办?range 方法只能得到 9 行。所以... WHERE id >=300 ORDER BY id LIMIT 10给你正好 10 并且不会被丢失的 id 所欺骗。
  • 更好的是:使用LIMIT 11. 这会浪费一点,因为它会占用额外的一行。[Next]但它可以让您知道是否在页面上包含按钮。如果返回 11 行,则有“下一页”。如果 <=10 行,则没有。这是一个很小的代价,可以让你的 UI 更加用户友好;你想要那个,不是吗?


归档时间:

查看次数:

3312 次

最近记录:

4 年,7 月 前