MySQL深度翻页和底层执行原理之间的关联和优化思路

1.翻页参数详解

limit 5000 , 10;
5000 (offset):跨过5000条记录
10(每页记录数):取10条
也就是 5001~5010
相关公式推断:
offset-》页:每页10条,跨过5000条,也就是5000/10=500页,跨过500页,也就是现在取的 5001~5010是第501页 通用公式:页 = offset/每页记录数
页-》offset:第501页,要跨500页,即跨500*10=5000条记录(offset)通用公式:offset=(页-1)*10

2.“深度翻页”一词的来源

selct * from t_user limit 5000 , 10;
这就是深度翻页,也就是跨很多记录取取数据。

3.MySQL底层执行原理

客户端将sql嵌入MySQL的server端提供的api,server端根据执行计划通过执行器操作执行引擎,执行引擎通过I/O获取记录返回给server端,server端再返回给客户端。总得来说就是:客户端-》server-》执行引擎-》磁盘I/O。具体调用过程如下:

4.那它和MySQL底层执行原理有什么孽缘呢?

select * from t_user order by key1 limit 5000, 10;
如果使用idx_key1执行上述查询,那么MySQL会这样处理:

  1. server层向InnoDB要第1条记录,InnoDB从idx_key1中获取到第一条二级索引记录,然后进 行回表操作得到完整的聚簇索引记录,然后返回给server层。server层准备将其发送给客户 端,此时发现还有个 LIMIT 5000, 10的要求,意味着符合条件的记录中的第5001条~5010才可以真 正发送给客户端,所以在这里先做个统计,我们假设server层维护了一个称作limit_count的变 量用于统计已经跳过了多少条记录,此时就应该将limit_count设置为1。
  2. server层再向InnoDB要下一条记录,InnoDB再根据二级索引记录的next_record属性找到下 一条二级索引记录,再次进行回表得到完整的聚簇索引记录返回给server层。server层在将其 发送给客户端的时候发现limit_count才是1,所以就放弃发送到客户端的操作,将limit_count 加1,此时limit_count变为了2。
  3. … 重复上述操作
  4. 直到limit_count等于5010的时候,server层才会真正的将InnoDB返回的5001~5010条完整聚簇索引记录发 送给客户端。
    从上述过程中我们可以看到,由于MySQL中是在实际向客户端发送记录前才会去判断LIMIT子句 是否符合要求,所以如果使用二级索引执行上述查询的话,意味着要进行5010次回表操作。server层在进行执行计划分析的时候会觉得执行这么多次回表的成本太大了,还不如直接全表扫描 +filesort快呢,所以就选择了后者执行查询。

5.如何通过优化sql来减少深度翻页的查询用时

既然深度翻页的成本是回表次数,那么我们就想办法减少回表次数:
a. 覆盖索引+join内连接
select * from t_user
join
(select id from t_user order by key1 limit 5000, 10) t_user_temp
on t_user.id = t_user_temp.id;
解析:
既让成本在于select id from t_user order by key1 limit 5000, 10,那么这处就不让它回表,采用覆盖索引,减少5010次回表,然后 join全表扫描。思考:join底层执行流程是怎么样的,在哪棵树操作的?
b. 主键游标(主键需自增)
select * from t_user where id > 0 order by id limit 0 , 10; //第1页
select * from t_user where id > 10 order by id limit 0 , 10; //第2页
select * from t_user where id > 20 order by id limit 0 , 10; //第3页

select * from t_user where id > 5000 order by id limit 0 , 10; //第6页
思考:使用游标的方案,一定要记得对游标列排序。为什么要这么做,自增id已经排序了啊。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fire king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值