技术分享
mysql的limit分页优化
来源:优码网     阅读:41
林风小破店
发布于 2023-11-27 00:47
查看主页

准备工作

4V%LUL)Y(Y$)F@QXQF(PVMB.png

# 总记录数为500000
mysql> select count(idfrom edu_test;
+-----------+
| count(id) |
+-----------+
|    500000 |
+-----------+
1 row in set (0.05 sec)

分析过程

从0开始查询10条:

mysql> select * from edu_test limit 010;

10 rows in set (0.05 sec)

从20万开始查询10条:

mysql> select * from edu_test limit 20000010;

10 rows in set (0.14 sec)

从50万开始查询10条:

mysql> select * from edu_test limit 49900010;

10 rows in set (0.21 sec)
mysql> explain select * from edu_test limit 20000010;
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------+
|
  1 | SIMPLE      | edu_test | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 499483 |   100.00 | NULL  |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------+
1 row in set (0.09 sec)

优化


思路:

方案1:通过有序唯一索引缩小扫描范围
前提必须要id有序,要不然结果会漏掉一部分数据的。

mysql> select * from edu_test where id > 499000 order by id asc limit 10;

10 rows in set (0.14 sec)

mysql> explain select * from edu_test where id > 499000 order by id asc limit 10;
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | edu_test | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL | 1000 |   100.00 | Using where |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.16 sec)
# 再缩小扫描范围
mysql> select * from edu_test where id between 499000 and 499020 order by id asc limit 10;

10 rows in set (0.09 sec)

mysql> explain select * from edu_test where id between 499000 and 499020 order by id asc limit 10;
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | edu_test | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |   21 |   100.00 | Using where |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.08 sec)

方案2:子查询

mysql> SELECT * FROM edu_test WHERE id >=  (SELECT id FROM edu_test ORDER BY id LIMIT 4990001) LIMIT 10;

10 rows in set (0.16 sec)

mysql> explain SELECT * FROM edu_test WHERE id >=  (SELECT id FROM edu_test ORDER BY id LIMIT 4990001) LIMIT 10;
+----+-------------+----------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
|  1 | PRIMARY     | edu_test | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |   1000 |   100.00 | Using where |
|  2 | SUBQUERY    | edu_test | NULL       | index | NULL          | PRIMARY | 4       | NULL | 499001 |   100.00 | Using index |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
2 rows in set (0.14 sec)

方案3:join查询

mysql> select * from edu_test s, (select id from edu_test order by id limit 49900010) t where s.id = t.id;

10 rows in set (0.16 sec)

mysql> explain select * from edu_test s, (select id from edu_test order by id limit 49900010) t where s.id = t.id;
+----+-------------+------------+------------+--------+---------------+---------+---------+------+--------+----------+-------------+
| id | select_type | table      | partitions | type   | possible_keys | key     | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+------------+------------+--------+---------------+---------+---------+------+--------+----------+-------------+
|
  1 | PRIMARY     | <derived2> | NULL       | ALL    | NULL          | NULL    | NULL    | NULL | 499010 |   100.00 | NULL        |
|  1 | PRIMARY     | s          | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | t.id |      1 |   100.00 | NULL        |
|
  2 | DERIVED     | edu_test   | NULL       | index  | NULL          | PRIMARY | 4       | NULL | 499010 |   100.00 | Using index |
+----+-------------+------------+------------+--------+---------------+---------+---------+------+--------+----------+-------------+
3 rows in set (0.10 sec)

实际业务场景


作者:sunpy
链接:https://www.jianshu.com/p/c5fb2dadbfe4

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 技术分享
相关推荐
基于JavaWeb的在线点餐系统
苹果ipa应用安装包ios系统闪退问题的可能性及解决方案
让搜索引擎为你带来源源不断的访客——不可不知的 SEO 实用技巧
网站建设有哪些困难,网站制作中常遇到哪些问题
一篇文章带你了解Python常用自动化测试框架——Pytest!

首页

消息

购物车

我的