在 SQL 中,什么更快:LIMIT ... OFFSET 或范围查询?
In SQL, what is faster: LIMIT ... OFFSET or range queries?
给定
以下架构:
CREATE TABLE employees (
name CHAR,
PRIMARY KEY id INT
);
table按id
排序
table.
中有100个1-100的唯一id
例子
| name | id |
|---------|----|
| Lynne | 1 |
| Johnny | 2 |
| D'Andra | 3 |
| Kimmel | 4 |
| ... |
Objective
获取10个id大于等于3的人
问题
使用 select name from employees order by id limit 10 offset 3
或 select name from employees where id >= 3 and id <13 order by id
会更快吗?为什么?
到目前为止我检查过的内容
Does adding 'LIMIT 1' to MySQL queries make them faster when you know there will only be 1 result?:这表示使用 limit 比不使用 limit 更快,但它没有将其与范围查询进行比较。
Select query with offset limit is too much slow:这说明偏移量通常很慢,因为它需要遍历所有行才能到达偏移量。它没有讨论对于任何整数 x?
使用 offset x
是否比 id >= x
慢
你的两个查询不一样。只有当您知道 id
列没有间隙并且(并且没有重复,但这对 id
有意义)时它们才相同。
对于小的偏移量,对于这样一个简单的查询应该没有什么区别。不过,我确实认为 MySQL 会读取 offset
查询的 all 结果,然后在达到偏移量时开始返回结果。也就是实际统计行数,然后输出offset后的那一行。
where
子句应使 MySQL 直接转到索引中的正确记录。对于更大的结果集,这应该更快。
也许这些都不是最优的。
网页中的一个常见做法是“分页”,其中第一个 'page' 显示 'first' 10 个项目,第二页显示下一个 10 个,依此类推
当您在列表中越走越远时,使用 OFFSET
会非常低效——在看到第 10 行之前,它必须小心翼翼地跨过每个“偏移”行。
如果 id
和 AUTOINCREMENT
,则无法保证 id 随着时间的推移会连续。删除、REPLACE
、INSERT IGNORE
、集群中的复制等可能会留下空白。当然,这个数字今天效果很好。但是你不应该相信明天有人“修复”了数据中的某些东西。
分页的最佳方法是“记住你离开的地方”。没有使用 OFFSET
。 id
(或其他一些唯一的列)只是一个 place-holder, 不是 一个数字。
更多详情:http://mysql.rjweb.org/doc.php/pagination
OP 的问题
Would it be faster to use 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, and why?
(让我修改数字以使答案更明显:)
limit 10 offset 300
-- 处理必须触及 300 行才能达到所需的 10 行;已触及 310 行。
where id >= 300 and id < 310
-- 假设在id
上有一个索引(可能是PRIMARY KEY
),只需要触及10行。
- 正如我在 link 中指出的那样,这避免了一个未提及的问题:如果删除了 id=305 的行怎么办?范围方法只会得到 9 行。所以...
WHERE id >=300 ORDER BY id LIMIT 10
正好得到 10,不会被丢失的 ID 所愚弄。
- 更好:使用
LIMIT 11
。这有点浪费,因为它占用了额外的一行。但它会让您知道是否在页面上包含 [Next]
按钮。如果返回 11 行,则有一个“下一页”。如果 <=10 行,则没有。这是让您的 UI 更加人性化的小代价;你想要那个,不是吗?
给定
以下架构:
CREATE TABLE employees ( name CHAR, PRIMARY KEY id INT );
table按id
排序table.
中有100个1-100的唯一id
例子
| name | id |
|---------|----|
| Lynne | 1 |
| Johnny | 2 |
| D'Andra | 3 |
| Kimmel | 4 |
| ... |
Objective
获取10个id大于等于3的人
问题
使用 select name from employees order by id limit 10 offset 3
或 select name from employees where id >= 3 and id <13 order by id
会更快吗?为什么?
到目前为止我检查过的内容
Does adding 'LIMIT 1' to MySQL queries make them faster when you know there will only be 1 result?:这表示使用 limit 比不使用 limit 更快,但它没有将其与范围查询进行比较。
Select query with offset limit is too much slow:这说明偏移量通常很慢,因为它需要遍历所有行才能到达偏移量。它没有讨论对于任何整数 x?
使用offset x
是否比 id >= x
慢
你的两个查询不一样。只有当您知道 id
列没有间隙并且(并且没有重复,但这对 id
有意义)时它们才相同。
对于小的偏移量,对于这样一个简单的查询应该没有什么区别。不过,我确实认为 MySQL 会读取 offset
查询的 all 结果,然后在达到偏移量时开始返回结果。也就是实际统计行数,然后输出offset后的那一行。
where
子句应使 MySQL 直接转到索引中的正确记录。对于更大的结果集,这应该更快。
也许这些都不是最优的。
网页中的一个常见做法是“分页”,其中第一个 'page' 显示 'first' 10 个项目,第二页显示下一个 10 个,依此类推
当您在列表中越走越远时,使用 OFFSET
会非常低效——在看到第 10 行之前,它必须小心翼翼地跨过每个“偏移”行。
如果 id
和 AUTOINCREMENT
,则无法保证 id 随着时间的推移会连续。删除、REPLACE
、INSERT IGNORE
、集群中的复制等可能会留下空白。当然,这个数字今天效果很好。但是你不应该相信明天有人“修复”了数据中的某些东西。
分页的最佳方法是“记住你离开的地方”。没有使用 OFFSET
。 id
(或其他一些唯一的列)只是一个 place-holder, 不是 一个数字。
更多详情:http://mysql.rjweb.org/doc.php/pagination
OP 的问题
Would it be faster to use 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, and why?
(让我修改数字以使答案更明显:)
limit 10 offset 300
-- 处理必须触及 300 行才能达到所需的 10 行;已触及 310 行。where id >= 300 and id < 310
-- 假设在id
上有一个索引(可能是PRIMARY KEY
),只需要触及10行。- 正如我在 link 中指出的那样,这避免了一个未提及的问题:如果删除了 id=305 的行怎么办?范围方法只会得到 9 行。所以...
WHERE id >=300 ORDER BY id LIMIT 10
正好得到 10,不会被丢失的 ID 所愚弄。 - 更好:使用
LIMIT 11
。这有点浪费,因为它占用了额外的一行。但它会让您知道是否在页面上包含[Next]
按钮。如果返回 11 行,则有一个“下一页”。如果 <=10 行,则没有。这是让您的 UI 更加人性化的小代价;你想要那个,不是吗?