首页 > 其他分享 >mybatis-plus分页插件之count优化

mybatis-plus分页插件之count优化

时间:2023-07-26 19:13:00浏览次数:42  
标签:count selectAll 插件 plus IPage sql page select

分页插件配置

package com.example.demo.conf;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan(basePackages = "com.example.demo.mapper")
public class MybatisPlusConfig {

    //配置分页插件注入容器
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

分页代码示例

分页查询control

 @PostMapping("/selectPage")
    public IPage<SplitExperimentType> selectAll(){
        Page page = new Page();
        page.setCurrent(1L);
        page.setSize(2L);
        IPage<SplitExperimentType> list = service.selectAll(page);
        return list;
    }

分页查询service

 @Override
    public IPage<SplitExperimentType> selectAll(Page page) {
        return baseMapper.selectAll(page);
    }

分页查询mapper

IPage<SplitExperimentType> selectAll(IPage page);

分页查询mapper.xml

<select id="selectAll" resultType="com.example.demo.model.SplitExperimentType">
    select * from split_experiment_type
</select>

优化前分页sql执行流程

1,先执行count统计,统计sql如下,规则时方法sql结果作为子查询,在外套一层select count(*) from (select * from split_experiment_type);

2, count > 0 ,在执行方法映射 sql

第一步:select count(*) from (select * from split_experiment_type);

第二步:select * from split_experiment_type limit xxx

性能分析

select count(*) from (select * from split_experiment_type)

这个sql肯定有问题,select * from split_experiment_type 会扫描全列,即使用明确列替换 * 也是会扫描在统计count是不需要的列;

期望是在count统计数,最优解是只统计符合条件的2级索引,或者主键索引,只统计索引列,性能刚刚的

但是统计count是sql是自动生成的,有什么办法不使用mybatis-plus的分页插件自动生成的count的sql呢,当然可以,下面我们看下mybatis-plus的分页插件部分源码

package com.baomidou.mybatisplus.extension.plugins.inner;


public class PaginationInnerInterceptor implements InnerInterceptor {
   
    public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        //获取page对象
        IPage<?> page = (IPage)ParameterUtils.findPage(parameter).orElse((Object)null);
        
        if (page != null && page.getSize() >= 0L && page.searchCount()) {
            //根据page对象的里的countId来查询是否配置了自定义count的方法,countId就是自定义统计sql的mapper里的方法名
            MappedStatement countMs = this.buildCountMappedStatement(ms, page.countId());
            BoundSql countSql;
            //如根据countId能获取MappedStatement,即存在自定义的方法执行,就执行自定义的mapper方法来统计count
            if (countMs != null) {
                
                countSql = countMs.getBoundSql(parameter);
            } 
            //如根据countId不能获取MappedStatement,就自己组装count统计sql
            else {
                countMs = this.buildAutoCountMappedStatement(ms);
                String countSqlStr = this.autoCountSql(page.optimizeCountSql(), boundSql.getSql());
                MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
                countSql = new BoundSql(countMs.getConfiguration(), countSqlStr, mpBoundSql.parameterMappings(), parameter);
                PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters());
            }

            CacheKey cacheKey = executor.createCacheKey(countMs, parameter, rowBounds, countSql);
            List<Object> result = executor.query(countMs, parameter, rowBounds, resultHandler, cacheKey, countSql);
            long total = 0L;
            if (CollectionUtils.isNotEmpty(result)) {
                Object o = result.get(0);
                if (o != null) {
                    total = Long.parseLong(o.toString());
                }
            }

            page.setTotal(total);
            return this.continuePage(page);
        } else {
            return true;
        }
    }

  ......
   
}

所以,可以看出如果我们在page对象中配置的countId(mapper里自定义统计count的方法名),并且存在mapper,存在countId对象值得统计方法(返回值是Long),并且在xml中进行了实现,就会走自定义的统计方法

优化后分页查询代码

controller的查询方法不变

service里

 @Override
    public IPage<SplitExperimentType> selectAll(Page page) {
        //指定自定义统计sql的方法名
        page.setCountId("selectAll_COUNT");
        return baseMapper.selectAll(page);
    }

mapper里新增一个selectAll_COUNT的方法

IPage<SplitExperimentType> selectAll(IPage page);
Long selectAll_COUNT(IPage page);

mapper.xml新增一个selectAll_COUNT方法的实现

<select id="selectAll" resultType="com.example.demo.model.SplitExperimentType">
        select * from split_experiment_type
</select>

<select id="selectAll_COUNT" resultType="java.lang.Long">
        SELECT COUNT(1) FROM split_experiment_type
</select>

优化后分页查询sql执行流程

第一步:SELECT COUNT(1) FROM split_experiment_type

第二步:select * from split_experiment_type limit xxx

count的统计可以通过自己想法进行优化,避免不必要的性能开支

 

 

标签:count,selectAll,插件,plus,IPage,sql,page,select
From: https://www.cnblogs.com/zhangzhiping35/p/17583335.html

相关文章

  • MyBatisPlus入门案例
              ......
  • zTree -- jQuery 树插件的使用包括添加、编辑(MVC)
    zTree--jQuery树插件网址:https://www.treejs.cn/v3/main.php#_zTreeInfo自行下载所需要的文件我自己写的一些具体示例:使用的.netCore6后端使用的ORM框架SqlSugar的中的ToTreeAsync方法返回的需要的数据格式,如果没用SqlSugar可以自己写递归来完成publicasyncTask<Resul......
  • 【JMeter】JMeter添加插件
    JMeter添加插件目录JMeter添加插件一、前言二、插件管理器三、推荐插件1.CustomThreadGroups(1)UltmateThreadGroup(2)SteppingThreadGroup2.3BasicGraph一、前言​ 在我们的工作中,我们可以利用一些插件来帮助我们更好的进行性能测试。今天我们来介绍下Jmeter怎么添加插件......
  • mybatisplus入门
    1. MybatisPlus的介绍MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。愿景我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。2.......
  • PlayWright(二十二)- allure插件(一)
    在上文中,我们介绍并使用了pytest-html插件,总之并不复杂,但是今天我们要讲一个比pytest-html插件强很多的插件allure报告,我们要掌握他并且灵活使用,之后的框架就不需要考虑其他的了 1.使用allure需要什么?因为allure的环境基于Java环境,所以得先下载JDK 下载JDK,配置环境变量因......
  • VSCode离线安装插件
    摘自:http://www.cbww.cn/news/58830.shtml一、前言工作环境屏蔽外网,无法在VSCode客户端在线VSCode插件商店下载插件。因此,只能下载插件文件,并离线安装。二、下载VSCode插件1.在VSCode插件商店中搜索需要的插件2.下载vsix格式插件 三、离线安装VSCode插件1.打开菜......
  • vue3之element-plus
    1.安装elementPlus和自动导入插件npmielementPlusnpminstall-Dunplugin-vue-componentsunplugin-auto-import2、配置自动按需导入//引入插件importAutoImportfrom'unplugin-auto-import/vite'importComponentsfrom'unplugin-vue-components/vite'import{......
  • MyBatis-Plus数据权限控制
    平时开发中遇到根据当前用户的角色,只能查看数据权限范围的数据需求。列表实现方案有两种,一是在开发初期就做好判断赛选,但如果这个需求是中途加的,或不希望每个接口都加一遍,就可以方案二加拦截器的方式。在mybatis执行sql前修改语句,限定where范围。当然拦截器生效后是全局性的,如何......
  • MyBatis-Plus这样实现动态SQL
    拦截器介绍拦截器是一种基于AOP(面向切面编程)的技术,它可以在目标对象的方法执行前后插入自定义的逻辑。MyBatis定义了四种类型的拦截器,分别是:Executor:拦截执行器的方法,例如update、query、commit、rollback等。可以用来实现缓存、事务、分页等功能。ParameterHandler:拦截参......
  • How to make sqlplus output appear in one line
    Howtomakesqlplusoutputappearinonelinehttps://dba.stackexchange.com/questions/54149/how-to-make-sqlplus-output-appear-in-one-line#SQL*PlusUser'sGuideandReferencehttp://docs.oracle.com/cd/E16655_01/server.121/e18404/ch_twelve040.htm#BAC......