来自:http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down 场景简而言之:一张超过 1600 万条记录的表 [2GB尺寸]。 SELECT 的 LIMIT 偏移量越大,查询速度越慢 b
来自:http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down
简而言之,场景:一个包含超过 1600 万条记录 [2GB 大小] 的表。使用 ORDER BY *primary_key*
时,SELECT 的 LIMIT 偏移量越高,查询速度就越慢所以
<code>SELECT * FROM large ORDER BY `id` LIMIT 0, 30 </code>
所需时间远少于
<code>SELECT * FROM large ORDER BY `id` LIMIT 10000, 30 </code>
这只订购 30 条记录,无论如何都是一样的。所以这不是 ORDER BY 的开销。
现在,获取最新 30 行大约需要 180 秒。如何优化这个简单的查询?
较高的偏移量会减慢查询速度,这是正常的,因为查询需要对第一个 OFFSET
+ LIMIT
记录进行计数(并且仅采用 LIMIT
记录)
他们)。该值越高,查询运行的时间越长。
查询无法直接转到 OFFSET
,因为,
首先,记录的长度可以不同,其次,删除的记录之间可能存在间隙。它需要检查并统计途中的每条记录。
假设 id
是
PRIMARY
KEY
表的 MyISAM
,
你可以使用这个技巧来加快速度:
<code>SELECT t.* FROM ( SELECT id FROM mytable ORDER BY id LIMIT 10000, 30 ) q JOIN mytable t ON t.id = q.id </code>
看这篇文章:
MySQL 无法直接转到第 10000 条记录(或者按照您的建议是第 80000 个字节),因为它不能假设它是这样打包/排序的(或者它具有 1 到 10000 之间的连续值)。尽管实际上可能是这样,但 MySQL 不能假设 没有漏洞/间隙/删除的 ID。
因此,正如 bob 所指出的,MySQL 将必须获取 10000 行(或遍历 id
上索引的第 10000 个条目)
在找到 30 个返回之前。
编辑:为了说明我的观点
请注意,虽然
<code>SELECT * FROM large ORDER BY id LIMIT 10000, 30 </code>
会慢(呃),
<code>SELECT * FROM large WHERE id > 10000 ORDER BY id LIMIT 30 </code>
将会快(呃),并且只要没有丢失id
,就会返回相同的结果
(即间隙)。
参考:
1.
http://timyang.net/data/key-list-pagination/