使用 PageHelper 插件分页查询很慢?一招帮你搞定!

点击上方“Java基基”,选择“设为星标”

做积极的人,而不是积极废人!

每天 14:00 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:huaweicloud.csdn.net/633562

aad3efff3090b54fc4.htm

019b9bf0a2f38c31eedf5af346a85442.jpeg


描述

在项目中使用Mybatis分页插件分页查询十分缓慢,但是在数据库中执行速度却很快?

该数据库的表共有10000条数据,分页查询时,在数据库中是很快,但是在使用Mybatis分页插件的时候居然8s多!

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

原因

PageHelper在做分页查询的时候,select count(0) 会先把原来的查询语句全部重新查询一遍(未做数量限制),然后再执行select count(0)操作,相当于查询两遍,导致查询速度慢。

例如:

select count(*) from ("原来的查询sql,相当于多查了一遍") user

sql打印:

SELECT count(0)
 FROM (SELECT V.*,B.TypeName AS TravelTypeName
 FROM (SELECT A.PKID, A.ApplyOrderNo FROM t1 AS A
 LEFT JOIN t2 AS P
 ON P.ApplyOrderNo = A.ApplyOrderNo
 LEFT JOIN t3 AS T
 ON A.UserCode = T.UserCode ) AS V
 LEFT JOIN t4 AS B
 ON V.TravelCode = B.TypeCode AND V.UserCode = B.UserCode AND B.Isdel = 0)
SELECT V.*,B.TypeName AS TravelTypeName
 FROM (SELECT A.PKID, A.ApplyOrderNo FROM t1 AS A
 LEFT JOIN t2 AS P
 ON P.ApplyOrderNo = A.ApplyOrderNo
 LEFT JOIN t3 AS T
 ON A.UserCode = T.UserCode ) AS V
 LEFT JOIN t4 AS B
 ON V.TravelCode = B.TypeCode AND V.UserCode = B.UserCode AND B.Isdel = 0

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

优化方案

在原来的查询方法后面,加上"_COUNT",重写总数量查询方法,优化sql,覆盖默认的数量查询方法。

bdac8ea2969cb5d37db8068fde624bda.png

例如:原来的mapper层里面的查询方法:

Page<Map<String, Object>> getOrderInfo(Map<String, Integer> map);

重写一个方法,getOrderInfo后面加“_COUNT”:返回类型必须为Long

Long getOrderInfo_COUNT();

然后在去xml中写具体sql:

<select id="getOrderInfo" resultType="Long" useCache="false">
 SELECT V.*,B.TypeName AS TravelTypeName
  FROM (SELECT A.PKID, A.ApplyOrderNo FROM t1 AS A
  LEFT JOIN t2 AS P
  ON P.ApplyOrderNo = A.ApplyOrderNo
  LEFT JOIN t3 AS T
  ON A.UserCode = T.UserCode ) AS V
  LEFT JOIN t4 AS B
  ON V.TravelCode = B.TypeCode AND V.UserCode = B.UserCode AND   B.Isdel = 0
</select>
<select id="getOrderInfo_COUNT" resultType="Long" useCache="false">
 SELECT
 COUNT(1)
 FROM t1 
</select>

注:getDeviceOrderInfo_COUNT()方法里面的sql自定义完成,尽量减少不必要的表关联,提高查询速率。

总结

分页插件中的计算Count的sql语句,会将需要分页的所有数据查出来然后生成一个临时表,再去计算Count。如果数据量比较大,生产临时表就多查询了一次表,会导致最后Count计算会十分慢,从而影响分页的结果。

解决办法

覆盖原Count的sql,根据官方文档自定义。注意返回值类型(Long)与方法名(原名_COUNT)



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

d3631c337eac58dec7c3c44e5727dfbb.png

已在知识星球更新源码解析如下:

85ef9b18207845ec1558655b22844423.jpeg

aa2129cee32a1e7ce27a8edc893d9bd9.jpeg

b90f8a4c0f88ef6d23e2fee5f61a4f54.jpeg

37e7492b63992aff0452f08e71cb6fba.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值