MySQL 中 limit 分页偏移量过大的优化

原因

  • 查询所有列导致回表

  • limit a, b会查询前a+b条数据,然后丢弃前a条数据

优化方案

两种,一般用覆盖索引,使用条件过滤有前提限制。

1. 覆盖索引

所谓的覆盖索引就是从非主聚簇索引中就能查到的想要数据,而不需要通过回表从主键索引中查询其他列,能够显著提升性能。

优化方案就是先查询得到主键id,然后再根据主键id查询其他列数据.

select * from user a join (select id from user where sex = 1 limit 10000000,10) b on a.id = b.id;

上面内容也许有点抽象,解释一下,因为 sex 是有索引,这里命中 sex 索引,而其 data 存储的是 主键值(即 id)那么可以直接得到,所以无需再回表。

回表: 如果查询不是 id 或者 sex ,而是其他字段,那么还要走一遍主索引(即 id 的 B+ 树),得到这个字段的数据。这就是回表。

详细可以看:mysql覆盖索引与回表

关于什么是 非聚簇索引 和 聚簇索引看:MySQL 之 非聚簇索引 和 聚簇索引

2. 条件过滤

基于排序做条件过滤,这样的方式优化是有条件的:主键 id 必须是有序的。在有序的条件下,也可以使用比如创建时间等其他字段来代替主键 id ,但是前提是这个字段是建立了索引的。

一般使用自增主键的时候可以使用这个方式

select * from user where sex = 1 and id > (select id from user where sex = 1 limit 10000000, 1) limit 10;

参考

MySQL中limit分页大偏移量的原因分析与优化方案

mysql覆盖索引与回表

MySQL 之 非聚簇索引 和 聚簇索引

posted @ 2021-04-13 23:17  东郊  阅读(1150)  评论(0编辑  收藏  举报