MySQL分页查询(limit用法详解、适用的性能优化场景)

分页常适用于性能优化,如以下场景:

  • 业务只需要获取部分数据,如top 10,此时查询所有数据到客户端,浪费数据库磁盘IO/网络IO、应用内存
  • 数据量太大,传输时间可能过长甚至中断、查询到客户端内存开销巨大,每次只查询较小数量的行,分多次查询

MySQL中使用limit实现分页查询。

基本语法

SELECT * FROM table 
LIMIT {[offset,] row_count | row_count OFFSET offset}

如上所示,limit可接受1或2个参数,参数必须是非负整数。

LIMIT offset, row_count

释义:从指定偏移位置开始返回,一共返回多少行

注意:第一行的偏移量为0,而不是1

例:SELECT * FROM tbl LIMIT 5,10,表示从第6行开始返回、一共返回10行。

这是MySQL分页最常见的写法。

LIMIT row_count

等价于LIMIT 0, row_count

LIMIT row_count OFFSET offset

为了兼容PostgreSQL,参见《PostgreSQL Limit分页》

例:LIMIT 10 OFFSET 5 等价于 LIMIT 5,10

推荐采用该方法,语义更明确、兼容性更好。

性能优化

执行器自动优化

MySQL执行器会自动优化含LIMIT的语句,包括但不限于如下情况:

  • limit较少行时,可能会直接进行全表扫描、而不走索引
  • limitorder bygroup bydistinct同时使用时,排序/聚合后的行数,一旦达到limitrow_count,排序/聚合就会停止。

    因为这个特性,如果多个行的排序列值相同,那么使用LIMIT时其返回的顺序可能不同。

  • limit 0会快速返回一个空结果集
  • MySQL一旦向客户端发送了所需的行数,它将立即终止查询

主动优化执行计划

加排序索引

limitorder by同时使用的概率非常高。如果排序列有索引,结合limit找到所需行数会立刻返回的特性,查询效率非常高
例:

SELECT * FROM tbl WHERE rid = 123 ORDER BY id LIMIT 50, 10

建议增加rid、id的联合索引(rid在前,这样索引会先匹配rid、然后再按id的顺序获取数据)。

偏移量较大时,使用索引

偏移量较大时,MySQL需要扫描过偏移量之前的所有行,然后再读取所需行返回,磁盘IO(随机IO)很多。因此分页查询越往后越慢。

SELECT * FROM tbl WHERE rid = 123 ORDER BY id LIMIT 100000, 10

实际上只需要10行数据,但是要在磁盘中遍历100000行后,才真正开始获取数据。

该情况可通过子查询优化:

SELECT * FROM 
	(SELECT id FROM tbl WHERE rid = 123 ORDER BY id LIMIT 100000, 10) temp 
	LEFT JOIN tbl t ON temp.id = t.id

通过子查询,可以直接在索引中获取到匹配行的主键。MySQL的索引是B+树,本身有序、并且节点中存放了主键,所以检索效率非常高。

这是索引覆盖的一个特例。当explainextra中出现using index时,即表示实现了索引覆盖。


以上。感谢您的阅读。

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值