为什么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秒。 我怎样才能优化这个简单的查询?

5 Solutions collect form web for “为什么MYSQL的LIMIT偏移量越来越慢?”

正常情况下,较高的偏移量会减慢查询速度,因为查询需要计数第一个OFFSET + LIMIT记录(并且只取其中的LIMIT )。 该值越高,查询运行时间越长。

查询不能进入OFFSET因为首先,记录的长度可能不同,其次,删除的记录可能存在差距。 它需要检查和计数每个记录的方式。

假设idMyISAM表的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的偏移量。

所以你可以做的是:

  1. 保存一组数据的最后一个id(30)(例如,lastId = 530)
  2. 添加条件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/

它也适用于字符串

  • MySQL Orderby一个数字,最后为空
  • mysql的顺序是,先是null,然后是DESC
  • 以很多字段排列列表(C#)?
  • 按顺序由ASC在底部的空值
  • Linqsorting,按组sorting?
  • Django:按位置sorting忽略NULL
  • MySQL - 控制哪个行由组返回
  • 如何在Grails中的多个字段中进行sorting?
  • 我如何订购我的SQLITE数据库降序,为一个Android应用程序?
  • MySQL'Order By' - 正确地排列字母数字
  • SQLite查询以不区分大小写的字母顺序