⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 huaweicloud.csdn.net/633562aad3efff3090b54fc4.htm 「慢积跬步」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

描述

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

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

原因

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

优化方案

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

例如:原来的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)

文章目录
  1. 1. 描述
  2. 2. 原因
  3. 3. 优化方案
  4. 4. 总结
  5. 5. 解决办法