这篇文章主要介绍了mysql分页查询如何优化的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇mysql分页查询如何优化文章都会有所收获,下面我们一起来看看吧。
分页查询的效率在数据量大的时候尤为重要,影响到前端响应和用户体验。
分页查询的优化方式
1、使用子查询优化
这种方式先定位偏移位置的 id,然后往后查询,这种方式适用于 id 递增的情况。
子查询优化原理:https://www.jianshu.com/p/0768ebc4e28d
select * from sbtest1 where k=504878 limit 100000,5;的查询过程:
首先会查询到索引叶子节点数据,然后根据叶子节点上的主键值去聚簇索引上查询需要的全部字段值。像下图左边这样,需要查询100005次索引节点,查询100005次聚簇索引的数据,最后再将结果过滤掉前100000条,取出最后5条。MySQL耗费了大量随机I/O在查询聚簇索引的数据上,而有100000次随机I/O查询到的数据是不会出现在结果集当中的。
既然一开始是利用索引的,为什么不先沿着索引叶子节点查询到最后需要的5个节点,然后再去聚簇索引中查询实际数据。这样只需要5次随机I/O,类似于上图右边的过程。这就是子查询优化,这种方式先定位偏移位置的id,然后往后查询,这种方式适用于id递增的情况。如下所示:
mysql> select * from sbtest1 where k=5020952 limit 50,1;
mysql> select id from sbtest1 where k=5020952 limit 50,1;
mysql> select * from sbtest1 where k=5020952 and id>=( select id from sbtest1 where k=5020952 limit 50,1) limit 10;
mysql> select * from sbtest1 where k=5020952 limit 50,10;
在子查询优化中,谓词中k是否有索引,对查询效率有很大影响,上述语句没有使用索引走全表扫描需要24.2s,走了索引后只需要0.67s。
mysql> explain select * from sbtest1 where k=5020952 and id>=( select id from sbtest1 where k=5020952 limit 50,1) limit 10;
+—-+————-+———+————+————-+—————+————+———+——-+——+———-+——————————————+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+———+————+————-+—————+————+———+——-+——+———-+——————————————+
| 1 | PRIMARY | sbtest1 | NULL | index_merge | PRIMARY,c1 | c1,PRIMARY | 8,4 | NULL | 19 | 100.00 | Using intersect(c1,PRIMARY); Using where |
| 2 | SUBQUERY | sbtest1 | NULL | ref | c1 | c1 | 4 | const | 88 | 100.00 | Using index |
+—-+————-+———+————+————-+—————+————+———+——-+——+———-+——————————————+
2 rows in set, 1 warning (0.11 sec)
但是这种优化方法也有局限性:
这种写法,要求主键ID必须是连续的
Where子句不允许再添加其他条件