PageHelper.startPage(1,3)
开始执行真正的select语句
public Page doSelectPage(ISelect select) { select.doSelect(); return this; }
进入MapperProxy类执行invoke方法获取到方法名称及参数值
接着是MapperMethod方法执行execute语句,判断是增、删、改、查。判断返回值是多个,进入executeForMany方法
这个方法开始调用SqlSessionTemplate、DefaultSqlSession等类获取到Mapper.xml文件的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 * from user where age = 10 limit 1,10;结果显示0.43s
当where条件后的结果集较大并且页数达到一个量级整个SQL的查询效率就十分低下(哪怕where的条件加上了索引也不行)。
select * from user where age = 10 limit 100000,10;结果显示4.73s
那有什么解决方案呢?
分页的方案 原来的分页SQL
select * from 表名 limilt 155555,20 1 优化后的sql语句
select * FROM 表名 WHERe ‘id’ in (select id from 表名 LIMIT 155555,20)
首先开启 PageHelper.startPage(pageParam.getPageNum(), pageParam.getPageSize()); 必然会在sql的后面追加 155555,20 而我们的优化后的SQL的limit是一个子查询语句如何解决?,此时仍然按照以前的做法会得到
SELECt * FROM 表名 WHERe ‘id’ in (select id from 表名 ) LIMIT 155555,20
Mapper文件