MySql分页查询慢

背景

我们在开发的过程中使用分页是不可避免的,通常情况下我们的做法是使用limit加偏移量:
select * from table where column=xxx order by xxx limit 1,20
当数据量比较小时(100万以内),无论你翻到哪一页,性能都是很快的。如果查询慢,只要在
where条件和order by 的列上加上索引就可以解决。但是,当数据量大的时候(小编遇到的情况
是500万数据),如果翻到最后几页,即使加了索引,查询也是非常慢的,这是什么原因导致的呢?我们该如何解决呢?

limit分页原理

当我们翻到最后几页时,查询的sql通常是:select * from table where column=xxx order by xxx limit 1000000,20
查询非常慢。但是我们查看前几页的时候,速度并不慢。这是因为limit的偏移量太大导致的。
MySql使用limit时的原理是(用上面的例子举例):

  1. MySql将查询出1000020条记录。
  2. 然后舍掉前面的1000000条记录。
  3. 返回剩下的20条记录。

上述的过程是在《高性能MySql》书中确认的。

解决方案

解决的方法就是尽量使用索引覆盖扫描,就是我们select后面检出的是索引列,而不是
所有的列,而且这个索引的列最好是id。然后再做一次关联查询返回所有的列。
上述的sql可以写成:

SELECT
    *
FROM
    table t
INNER JOIN (
    SELECT
        id
    FROM
        table
    WHERE
        xxx_id = 143381
    LIMIT 800000,20
) t1 ON t.id = t1.id

我们在mysql中做的真实的实验:

image1

上图是没有优化过的sql,执行时间为2s多。经过优化后如下:

image2

执行时间为0.3s,性能有了大幅度的提升。虽然做了优化,但是随着偏移量的增加,性能也会随着下降,MySql官方虽然也给出了
其他的解决方案,但是在实际开发中很难使用。

有的同学可能会问,能不能使用IN嵌套子查询,而不使用INNER JOIN的方式,答案是不可以,因为MySql在子查询中不能使用LIMIT

MySql分页优化就先介绍到这里了。

转自:https://yq.aliyun.com/articles/642050?spm=a2c4e.11153940.blogcont637297.16.24e35a83HLNxxF

### MySQL 分页查询面试常见问题及答案 #### 一、分页查询的基础概念 分页查询是指当数据量较大时,为了提高用户体验和系统性能,将大量数据分成若干个小部分逐步展示的技术。在MySQL中,`LIMIT`子句常用于实现这一目的。 ```sql SELECT * FROM table_name LIMIT offset, row_count; ``` 此语法表示跳过前`offset`条记录并返回随后的`row_count`条记录[^2]。 #### 二、传统分页方法存在的问题 随着偏移量增大,即页面越往后翻阅,所需扫描的数据行数越多,这会导致严重的性能下降。对于拥有海量数据的大表而言尤为明显。每次请求都会造成全表扫描直到达到指定位置,从而增加了I/O开销以及锁等待时间。 #### 三、优化策略之一——基于主键范围查找 为了避免上述弊端,推荐采用基于主键或其他唯一索引字段的方式来进行分页操作: ```sql SELECT * FROM orders WHERE id > last_seen_id ORDER BY id ASC LIMIT page_size; ``` 这里假定`id`为主键列,并且按照升序排列;通过记住上一次获取到的最大ID(`last_seen_id`)来定位下一页起始点,这样可以有效减少不必要的遍历过程,显著改善响应速度[^3]。 #### 四、利用覆盖索引来加速读取 如果能够确保所选中的所有列都已建立合适的索引,则可以直接从索引树结构中提取所需信息而无需访问实际存储区内的原始行数据。这种方式被称为“覆盖索引”,它能极大程度降低磁盘IO成本,进而加快检索效率。 例如,在设计之初就考虑到可能涉及频繁分页显示的需求,提前规划好相应的复合索引组合,以便尽可能多地满足此类应用场景下的快速访问需求。 #### 五、其他注意事项 - **避免使用`ORDER BY RAND()`**:随机排序会强制整个表格参与运算,破坏了原有顺序关系,不利于后续增量加载; - **合理设置每页大小**:过大可能导致单次传输过多内容影响前端渲染效果,太小则增加网络交互次数拖整体流程; - **考虑缓存机制**:对于那些变动不频繁但又经常被浏览的部分列表项,适当引入客户端侧或服务端内存级缓存措施有助于减轻服务器负担。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值