当前位置: 代码网 > it编程>数据库>Mysql > MySQL limit分页查询如何优化性能

MySQL limit分页查询如何优化性能

2026年09月03日 Mysql 我要评论
mysql通过 limit 实现分页查询。limit 接收一个或两个整数型参数。如果是两个参数,第一个指定返回记录行的偏移量,第二个指定返回记录行的最大数目。初始记录行的偏移量是 0。为了与 post

mysql通过 limit 实现分页查询。limit 接收一个或两个整数型参数。

如果是两个参数,第一个指定返回记录行的偏移量,第二个指定返回记录行的最大数目。初始记录行的偏移量是 0。为了与 postgresql 兼容,limit 也支持limit a offset b【a:取的记录数;b:索引】。

一、分页查询

客户端通过传递 start(页码),pagesize(每页显示的条数) 两个参数去分页查询数据库表中的数据。

mysql 数据库提供的分页函数 limit m,n 用法和实际需求不切合,所以就需要根据实际情况去改写适合分页的语句。

1、查询第1条到第10条的数据select * from table limit 0,10;

—>对应需求就是查询第一页的数据:

select * from table limit (1-1)*10,10;

2、查询第11条到第20条的数据select * from table limit 10,10;

—>对应需求就是查询第二页的数据:

select * from table limit (2-1)*10,10;

3、查询第21条到第30条的数据select * from table limit 20,10;

—>对应需求就是查询第三页的数据:

select * from table limit (3-1)*10,10;

由此,得出符合需求的分页 sql 格式是:

select * from table limit (start-1)*pagesize,pagesize;

其中 start 是页码,pagesize 是每页显示的条数。

二、性能问题

对于小的偏移量,直接用 limit 查询没有什么问题。随着数据量的增大,越往后分页,limit 语句的偏移量越大,速度也会明显变慢。

优化思想:

避免数据量大时扫描过多的记录

解决:

子查询的分页方式或者 join 分页方式。join 分页和子查询分页的效率基本在一个等级上,消耗的时间也基本一致。

一般 mysql 的主键是自增的数字类型,该情况可以使用下面的方式进行优化。

以真实的生产环境的 6 万条数据的一张表为例,比较一下优化前后的查询耗时:

-- 传统 limit,文件扫描
select * from table order by id limit 50000,2;
受影响的行: 0
时间:  0.171s

-- 子查询方式,索引扫描
select * from table
where id >= (select id from table order by id limit 50000 , 1)
limit 2;
受影响的行: 0
时间: 0.035s

-- join 分页方式
select * from table as t1
join (select id from table order by id limit 50000, 1) as t2
where t1.id <= t2.id 
order by t1.id limit 2;
受影响的行: 0
时间: 0.036s

可以看到经过优化性能提高了很多倍。

优化原理:

子查询是在索引上完成的,而普通的查询是在数据文件上完成的。

通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。因为要取出所有字段内容,普通查询需要跨越大量数据块并取出,而另一种方式直接根据索引字段定位后,才取出相应内容,效率自然大大提升。因此,对 limit 的优化,是避免直接使用 limit,而是首先获取到 offset 的 id,然后直接使用 limit size 来获取数据。

在实际项目使用,可以利用类似策略模式的方式去处理分页。

例如,每页 100 条数据,判断如果是 100 页以内,就使用最基本的分页方式;如果大于 100,则使用子查询的分页方式。

三、limit 优化。使用合理的分页方式以提高分页的效率

使用 limit 实现分页逻辑。不仅提高了性能,同时减少了不必要的数据库和应用间的网络传输。

查询结果只有一条或者只要最大/最小一条记录,建议用 limit 1。这是为了使explain中 type 列达到 const 类型。“limit 1”可以避免全表扫面,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。当然,如果查询字段是唯一索引的话,没必要加 limit 1,因为 limit 的存在主要就是为了防止全表扫描,从而提高性能,如果一个语句本身可以预知不用全表扫描,有没有 limit,性能的差别并不大。

使用如下语句做分页的时候,随着表数据量的增加,直接使用 limit 分页查询会越来越慢。

select id,name from product limit 89757, 20

优化如下:可以取前一页的最大行数的 id,然后根据这个最大的 id 来限制下一页的起点。此例中上一页最大的 id 是 89756。

sql 可以采用如下的写法:

//方案一 :返回上次查询的最大记录(偏移量)
select id,name from product where id> 89756 limit 20
//方案二:order by + 索引
select id,name from product order by id  limit 10000,10
//方案三:在业务允许的情况下限制页数

理由如下:

  • 当偏移量最大的时候,查询效率就会越低,因为 mysql 并非是跳过偏移量直接去取后面的数据,而是先把偏移量+要取的条数,然后再把前面偏移量这一段的数据抛弃掉再返回的。
  • 如果使用优化方案一,返回上次最大查询记录(偏移量),这样可以跳过偏移量,效率提升不少。
  • 方案二使用 order by+索引,也是可以提高查询效率的。
  • 方案三的话,建议跟业务讨论,有没有必要查这么多的分页。因为绝大多数用户都不会往后翻太多页。
  • 【强制】在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

四、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com