当前位置: 首页 > 后端技术 > Java

查询效率提升10倍!3个优化方案帮你解决MySQL深度分页问题

时间:2023-04-01 13:30:11 Java

开发中经常会遇到分页查询的需求,但是当翻页过多时,就会出现深度分页,导致查询效率急剧下降。有什么办法可以解决深度分页的问题吗?本文总结了三种优化方案,查询效率直接提升10倍。让我们一起学习。1、准备数据,先创建user表,只在create_time字段加索引:CREATETABLE`user`(`id`intNOTNULLAUTO_INCREMENTCOMMENT'primarykey',`name`varchar(255)DEFAULTNULLCOMMENT'name',`create_time`timestampNULLDEFAULTNULLCOMMENT'creationtime',PRIMARYKEY(`id`),KEY`idx_create_time`(`create_time`))ENGINE=InnoDBCOMMENT='usertable';然后将100万插入用户表您可以在此处使用存储过程:dropPROCEDUREIFEXISTSinsertData;DELIMITER$$createprocedureinsertData()begindeclareiintdefault1;当我<=100000执行INSERT到用户(name,create_time)VALUES(CONCAT("name",i),now());设置我=我+1;结束时;结束$$调用insertData()$$2。验证每页10项的深度分页问题。当我们查询第一页时,速度很快:select*fromuserwherecreate_time>'2022-07-03'limit0,10;不到0.01秒直接返回,所以没有显示执行时间。当我们翻到10000页时,查询效率急剧下降:select*fromuserwherecreate_time>'2022-07-03'limit100000,10;执行时间变成了0.16秒,性能至少下降了几十倍。主要时间花在哪里?需要扫描前10条数据,数据量大,需要时间。create_time是一个非聚集索引。需要先查询主键ID,再回表查询。使用主键ID查询所有字段,画出一张表的查询流程:1、首先通过create_time查询主键ID2。然后通过主键ID查询表中的所有字段。不要问为什么B+树的结构是这样的?问是规则。你可以看看前两篇文章。你可以看看前两篇文章。为什么MySQL索引的底层实现要用B+树?一篇文章把MySQL的clustering/joint/coveringindex,tablereturn,indexpushdown搞清楚了,然后我们针对这两个耗时的原因进行优化。3、优化查询3.1使用子查询先使用子查询找出满足条件的主键,然后以主键ID为条件找出所有字段。select*fromuserwhereidin(selectidfromuserwherecreate_time>'2022-07-03'limit100000,10);但是这个查询会报错,说子查询不支持使用limit。我们可以加一层子查询嵌套:select*fromuserwhereidin(selectidfrom(selectidfromuserwherecreate_time>'2022-07-03'limit100000,10)ast);执行时间缩短为0.05秒,减少了0.12秒,相当于查询性能提升了三倍。为什么使用子查询先找出符合条件的主键ID可以缩短查询时间呢?我们可以通过解释检查执行计划来理解:explainselect*fromuserwhereidin(selectidfrom(selectidfromuserwherecreate_time>'2022-07-03'limit100000,10)ast);可以看到Extra列显示子查询中使用了Using索引,说明使用了覆盖索引,所以子查询不需要回表查询,加快了查询效率。3.2使用innerjoin关联查询,将子查询的结果当做临时表,再与原表进行关联查询。select*fromuserinnerjoin(selectidfromuserwherecreate_time>'2022-07-03'limit100000,10)astonuser.id=t.id;查询性能与使用子查询相同。3.3使用分页游标(推荐)的实现方法是:当我们查询第二页时,将第一页的查询结果放入第二页的查询条件中。例如:先查询第一页select*fromuserwherecreate_time>'2022-07-03'limit10;然后查询第二页,将第一页的查询结果放入第二页的查询条件中:select*fromuserwherecreate_time>'2022-07-03'andid>10limit10;这样就相当于每次都查询第一页,不存在深分页的问题。推荐使用。执行时间0秒,查询性能直接提升几十倍。这种查询方式虽然简单易用,但是带来了另一个问题,就是无法跳转到指定页码,每次只能向下滚动一页。所以这种查询只适用于特定场景,比如某资讯APP的首页。互联网APP一般采用瀑布流的形式,比如百度首页、今日头条首页,总是向下滑动翻页,不需要跳转到指定页数。不信你看一下,这是头条的瀑布流:传递的参数中包含了上一页的查询结果。在响应数据中,返回下一页查询条件。所以这个查询方式的应用场景还是挺广的,赶紧用起来吧。知识点总结:文章持续更新中。可以在微信搜索“一光架构”第一时间阅读更多技术干货。