分页插件pagehelper统计的数量不对加where筛选
项目一直使用的是PageHelper实现分页功能,项目前期数据量较少一直没有什么问题。随着业务扩增,数据库扩增PageHelper出现了明显的性能问题。几十万甚至上百万的单表数据查询性能缓慢,需要几秒乃至十几秒的查询时间。故此特地研究了一下PageHelper源码,查PageHelper分页的实现方式。
一段较为简单的查询,跟随debug开始源码探寻之旅。
主要保存由前端传入的pageNum(页数)、pageSize(每页显示数量)和count(是否进行count(0)查询)信息。
开始执行真正的select语句
进入MapperProxy类执行invoke方法获取到方法名称及参数值
接着是MapperMethod方法执行execute语句,判断是增、删、改、查。判断返回值是多个,进入executeForMany方法
这个方法开始调用SqlSessionTemplate、DefaultSqlSession等类获取到l文件的SQL语句
开始进入PageHelper的真正实现,Plugin通过实现InvocationHandler进行动态代理获取到相关信息
PageInterceptor实现Mybatis的Interceptor接口,进行拦截
转到ExecutorUtil抽象类的pageQuery方法
在抽象类AbstractHelperDialect的getPageSql获取到对应的Page对象
进入到MySqlDialect类的getPageSql方法进行SQL封装,根据page对象信息增加Limit。分页的信息就是这么拼装起来的
将最后拼装好的SQL返回给DefaultSqlSession执行查询并返回
至此整个查询过程完成,原来PageHelper的分页功能是通过Limit拼接SQL实现的。查询效率低的问题也出来了,那么应该如何解决。
首先分析SQL语句,limit在数据量少或者页数比较靠前的时候查询效率是比较高的。(单表数据量百万进行测试)
select*fromuserwhereage=10limit1,10;结果显示0.43s
当where条件后的结果集较大并且页数达到一个量级整个SQL的查询效率就十分低下(哪怕where的条件加上了索引也不行)。
select*fromuserwhereage=10limit100000,10;结果显示4.73s
SELECTa.*FROMUSERa
INNERJOIN
(SELECTidFROMUSERWHEREage=10LIMIT100000,10)b
ONa.id=b.id;
结果0.53s
分页查询插件完美解决了查询效率问题其中需要对where条件增加索引,id因为是主键自带索引。select返回减少回表可以提升查询性能,所以采用查询主键字段后进行关联大幅度提升了查询效率。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。