mysql-深分页优化

举报
object 发表于 2024/03/25 16:30:32 2024/03/25
【摘要】 可能大部分人都没遇到过limit的性能问题,其实mysql的limit 页码值越大,执行的时间就越长。对于一些大容量的表可能就会存在性能问题。limit深分页为什么会变慢?这个主要是limit offset,size 不是跳过offset行,取N行,而是获取offset + N行,然后社区offset行。具体limit的SQL执行流程如下:通过普通的索引树,过滤业务筛选条件,找到满足的记录I...

可能大部分人都没遇到过limit的性能问题,其实mysql的limit 页码值越大,执行的时间就越长。对于一些大容量的表可能就会存在性能问题。

limit深分页为什么会变慢?

这个主要是limit offset,size 不是跳过offset行,取N行,而是获取offset + N行,然后社区offset行。

具体limit的SQL执行流程如下:

  • 通过普通的索引树,过滤业务筛选条件,找到满足的记录ID
  • 通过ID,回到主键索引树,找到满足记录的行,然后取出展示的列(回表
  • 扫描满足条件的offset+size行,然后舍去前offset行,返回。

其中需要注意的就是回表,也是产生性能问题的关键,当深分页的时候,需要取出的列越多,回表的次数越多,所以越慢。

常见优化策略

优化策略核心就是减少回表次数。

子查询或延迟关联

子查询和延迟关联原理都是一样的,通过查询出符合的数据ID,通过ID索引查询代替回表操作

  • 子查询:
    select id,name,balance FROM account where id >= (select a.id from account a where a.update_time >= '2020-09-19' limit 100000, 1) LIMIT 10;
    
  • 延迟查询:
    SELECT  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.update_time >= '2020-09-19' ORDER BY a.update_time LIMIT 100000, 10) AS  acct2 on acct1.id= acct2.id;
    

回表次数都是10次。

标签记录法

标签记录法需要有前置条件,子查询是通过自己查询第1000000行,而标签记录法的优化,则需要查询以前,就已经知道了第100000行的ID是什么,则此时直接走ID索引即可。

select  id,name,balance FROM account where id > 100000 order by id limit 10;

覆盖索引

索引中已经包含了所有需要获取的字段的查询方式称为覆盖索引。

回表的目的就是获取索引以外的数据列,如果索引中已经包含了需要的数据,则不再需要进行回表操作,前提是需要查询的列为覆盖索引。

# 如果只需要查询 id, code, type 这三列,可建立 code 和 type 的覆盖索引
SELECT id, code, type FROM t_order
ORDER BY code
LIMIT 1000000, 10;

// todo 覆盖索引更多的了解

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。