为什么MYSQL的LIMIT偏移量越来越慢?
情景简介:一张拥有超过1600万条记录的表格[2GB大小]。 SELECT使用的LIMIT偏移量越高,查询变得越慢,使用ORDER BY * primary_key *
所以
SELECT * FROM large ORDER BY `id` LIMIT 0, 30
远远不及
SELECT * FROM large ORDER BY `id` LIMIT 10000, 30
那只能下令30个记录,而且也是一样的。 所以这不是ORDER BY的开销。
现在,当获取最新的30行时,大约需要180秒。 我怎样才能优化这个简单的查询?
正常情况下,较高的偏移量会减慢查询速度,因为查询需要计数第一个OFFSET + LIMIT
记录(并且只取其中的LIMIT
)。 该值越高,查询运行时间越长。
查询不能进入OFFSET
因为首先,记录的长度可能不同,其次,删除的记录可能存在差距。 它需要检查和计数每个记录的方式。
假设id
是MyISAM
表的PRIMARY KEY
,可以使用这个技巧加速它:
SELECT t.* FROM ( SELECT id FROM mytable ORDER BY id LIMIT 10000, 30 ) q JOIN mytable t ON t.id = q.id
看到这篇文章:
- MySQL ORDER BY / LIMIT性能:后期查询
我自己也有同样的问题。 鉴于你想收集大量的这些数据,而不是一个特定的一组30,你可能会运行一个循环,并增加30的偏移量。
所以你可以做的是:
- 保存一组数据的最后一个id(30)(例如,lastId = 530)
- 添加条件
WHERE id > lastId limit 0,30
所以你总是可以有一个零偏移。 性能改进你会感到惊讶。
MySQL不能直接进入第10000个记录(或者你的建议的第80000个字节),因为它不能假设它是这样打包/排序的(或者它的连续值在1到10000之间)。 尽管实际上可能是这样,MySQL不能认为没有漏洞/间隙/删除ID。
因此,正如Bob所指出的那样,MySQL将不得不取回10000行(或者遍历id
上的第10000个索引条目),然后才能找到30个返回值。
编辑 :说明我的观点
请注意,虽然
SELECT * FROM large ORDER BY id LIMIT 10000, 30
会很慢(呃) ,
SELECT * FROM large WHERE id > 10000 ORDER BY id LIMIT 30
会很快(呃) ,并且会返回相同的结果,只要没有缺失的id
(即间隙)。
两个查询中耗时的部分是从表中检索行。 从逻辑上讲,在LIMIT 0, 30
版本中,只需要检索30行。 在LIMIT 10000, 30
版本中,计算10000行,返回30行。 在我的数据读取过程中可以做一些优化,但要考虑以下几点:
如果你在查询中有一个WHERE子句呢? 引擎必须返回所有符合条件的行,然后对数据进行排序,最后得到30行。
还要考虑在ORDER BY序列中不处理行的情况。 所有符合条件的行都必须进行排序以确定返回哪些行。
我发现一个有趣的例子来优化SELECT查询ORDER BY id LIMIT X,Y。 我有35万行,所以花了2分钟找到一个行的范围。
诀窍是:
select id, name, address, phone FROM customers WHERE id > 990 ORDER BY id LIMIT 1000;
只要把你的最后一个id的地方增加了很多的表现。 对我来说是从2分钟到1秒:)
其他有趣的技巧在这里: http : //www.iheavy.com/2013/06/19/3-ways-to-optimize-for-paging-in-mysql/
它也适用于字符串