这是正常的翻页的业务需求.

在一张 count 为 200w 的表上执行一下 sql:

select * from table_name limit 1000000,5

执行时间:25s

问题:
MySQL 里对 LIMIT OFFSET 的处理方式是,取出 OFFSET+LIMIT 的所有数据,然后去掉 OFFSET,返回底部的 LIMIT。
这种方式在 offset 很高的情况下,如:limit 100000,20,这样系统会查询 100020 条,然后把前面的 100000 条都扔掉,这是开销很大的操作,导致慢查询很慢.

如何优化:

用 id>m limit n 取代,比用 limit m,n 快很多,原因在于与利用上了主键索引, 只查询了 n 条记录. 这种方法很适合数据加载,但是不一定适合前台的翻页场景,
因为 ID 可能不连续, 在电梯模式的翻页中不适用,只是用扶梯模式的翻页。

select * from 表 where id > 1000000 limit 5

执行一下:0.013s
还有一个简单的优化办法是使用覆盖查询(covering index)查询,然后再跟全行的做 join 操作。这样可以直接使用 index 得到数据,而不去查询表,当找到需要的数据之后,在与全表 join,获得其他的列。
比如:

select * from table_name inner join (select id from table_name limit 1000000,5) as tmp on tmp.id = table_name.id

执行时间:0.211s

最后修改:2019 年 07 月 05 日 05 : 30 PM
打赏不打超过你工资的一半!