MyBatis 分页查询优化实例(用好子查询,事关功倍)

8 篇文章 0 订阅

如下图所示的这种列表应该是系统里最常见的了。随着数据的增长,查询的速度也将越来越慢,那就需要优化了。
数据库使用的是mysql, 分页命名用的是mybatis plus 的paging插件。
在这里插入图片描述

优化的手段

  1. 加上条件限制,像这个页面应该加上时间范围限制,只能查一个月的或者一年的数据。
  2. SQL查询优化。

今天重点是讲怎么去优化SQL。

SQL优化

一:优化前

1:Mapper 代码

    <select id="getPages" resultType="com.ly.mp.swcas.main.entities.Retrospect">
        SELECT
        r.*,
        v.LOOKUP_VALUE_NAME,
        v.LOOKUP_VALUE_CODE,
        s.VIN
        FROM
        t_swcas_bu_retrospect As  r
        LEFT JOIN t_swcas_db_lookup_value As v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE AND v.COMM_TYPE_CODE = 'swcas_trace_no'
        and r.IS_ENABLE=1
        LEFT JOIN t_swcas_bu_sale  As  s  ON  r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER and s.IS_ENABLE=1
        <where>
        <if test="sapOrderNo != null and sapOrderNo !='' ">
            and r.SAP_ORDER_NO = #{sapOrderNo}
        </if>
        <if test="mesProductionNo != null and mesProductionNo !=''">
            and r.MES_PRODUCTION_NO = #{mesProductionNo}
        </if>
        <if test="retrospectPartNo != null and retrospectPartNo !='' ">
            and r.RETROSPECT_PART_NO = #{retrospectPartNo}
        </if>
        <if test="vin != null and vin !='' ">
                and s.VIN = #{vin}
        </if>
            <if test="lookUpValueName != null and lookUpValueName !='' ">
                and LOOKUP_VALUE_NAME = #{lookUpValueName}
            </if>
        </where>
    </select>

2:使用mybatis plus分页会产成两个脚本(不使用任务条件的情况下)。分别是:

1):页数据查询

SELECT
        r.*,
        v.LOOKUP_VALUE_NAME,
        v.LOOKUP_VALUE_CODE,
        s.VIN
        FROM
        t_swcas_bu_retrospect As  r
        LEFT JOIN t_swcas_db_lookup_value As v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE AND v.COMM_TYPE_CODE = 'swcas_trace_no'
        and r.IS_ENABLE=1
        LEFT JOIN t_swcas_bu_sale  As  s  ON  r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER and s.IS_ENABLE=1 limit 10,10

2):总数查询

SELECT
	count(1)
FROM
	t_swcas_bu_retrospect AS r
LEFT JOIN t_swcas_db_lookup_value AS v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE
AND v.COMM_TYPE_CODE = 'swcas_trace_no'
AND r.IS_ENABLE = 1
LEFT JOIN t_swcas_bu_sale AS s ON r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER
AND s.IS_ENABLE = 1;

3):耗时结果

1 页数据查询很快,耗时0.003秒。
2 总数查询慢,耗时8秒。
数量为:80万。

结果如用户反馈一样,非常慢。。

分析

1:业务表分析

t_swcas_bu_retrospect 零件追溯表(开发环境80W数据,生产500W)
t_swcas_db_lookup_value 键值表 (数据量1000)
t_swcas_bu_sale 销售表(开发环境 30W, 生产100万)

SQL优化思路

1:t_swcas_bu_retrospect 、t_swcas_bu_sale 两个大表关联,实际上只为了取销售表里的一个字段。优化:使用子查询处理
2:与值列表关联使用inner join。确认是能一一对应上的。把r.IS_ENABLE = 1 放在 where 之后。
3:第2步去掉了 t_swcas_bu_sale 关联,那么 t_swcas_bu_sale 对应的条件也要处理。如下
and r.SAP_ORDER_NO in (select s.PLANNED_ORDER_NUMBER from t_swcas_bu_sale s where s.vin = #{vin})

结体SQL优化如下:

<select id="getPages" resultType="com.ly.mp.swcas.main.entities.Retrospect">
        SELECT
        r.*,
        v.LOOKUP_VALUE_NAME,
        v.LOOKUP_VALUE_CODE,
        v.EXT_COL01 AS LOOKUP_VALUE_EN_NAME,
        (select s.VIN from t_swcas_bu_sale s where  s.IS_ENABLE=1 and r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER limit 1 ) as VIN
        FROM
        t_swcas_bu_retrospect As  r
        inner JOIN t_swcas_db_lookup_value As v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE AND v.COMM_TYPE_CODE = 'swcas_trace_no'
        where  r.IS_ENABLE=1
        <if test="sapOrderNo != null and sapOrderNo !='' ">
            and r.SAP_ORDER_NO = #{sapOrderNo}
        </if>
        <if test="mesProductionNo != null and mesProductionNo !=''">
            and r.MES_PRODUCTION_NO = #{mesProductionNo}
        </if>
        <if test="retrospectPartNo != null and retrospectPartNo !='' ">
            and r.RETROSPECT_PART_NO = #{retrospectPartNo}
        </if>
        <if test="vin != null and vin !='' ">
           and r.SAP_ORDER_NO in (select s.PLANNED_ORDER_NUMBER  from   t_swcas_bu_sale s where  s.vin = #{vin})
        </if>
        <if test="lookUpValueName != null and lookUpValueName !='' ">
                and LOOKUP_VALUE_NAME = #{lookUpValueName}
        </if>
        order by r.created_date desc
    </select>

索引创建

1:根据排序字段创建索引

create index ix_t_swcas_bu_retrospect_CreatedDate on t_swcas_bu_retrospect  (created_date desc)

2:根据关联字字段创建索引

create index ix_t_swcas_bu_retrospect_RETROSPECT_PART_NO  on t_swcas_bu_retrospect  (RETROSPECT_PART_NO )

测试:

1:查询页数据,如下图所示,耗时16毫秒,符合要求。
在这里插入图片描述
2:查询总数,耗时0.6秒,符合优化条件。

在这里插入图片描述
优化完成。开发环境 页面响应少于2秒,业务环境 响应少于3秒。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis提供了一种方便的方式来进行分页查询。在使用MyBatis进行分页查询时,我们需要使用两个参数:offset(偏移量)和limit(每页记录数)。接下来,我将向您展示如何在MyBatis中使用分页查询。 首先,在Mapper.xml文件中,我们需要添加一个select语句来进行分页查询。以下是一个示例: ```xml <select id="getUsers" resultType="User"> SELECT * FROM users LIMIT #{offset}, #{limit} </select> ``` 在这个示例中,`getUsers`是查询的id,`User`是返回结果的类型,`users`是数据表的名称。 然后,在Java代码中,我们可以使用PageHelper类来设置分页参数。以下是一个示例: ```java int pageNo = 1; // 当前页码 int pageSize = 10; // 每页记录数 PageHelper.startPage(pageNo, pageSize); // 设置分页参数 List<User> userList = userDao.getUsers(); // 执行分页查询 // 处理查询结果 for (User user : userList) { System.out.println(user); } // 获取分页信息 PageInfo<User> pageInfo = new PageInfo<>(userList); System.out.println("总记录数:" + pageInfo.getTotal()); System.out.println("总页数:" + pageInfo.getPages()); System.out.println("当前页码:" + pageInfo.getPageNum()); System.out.println("每页记录数:" + pageInfo.getPageSize()); ``` 在这个示例中,`userDao`是一个数据访问对象,`User`是结果对象类型。我们使用`startPage`方法设置分页参数,然后调用查询方法`getUsers`来执行分页查询。最后,我们可以使用`PageInfo`对象获取分页信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值