SQL,查询条件中IN的内容过多效率低进行优化

前提:

        业务实施过程中,查询分页数据很慢,后定位到是in的数据过多,导致查询很慢。

优化思路:

        使用临时表解决,将数据插入到一临时表中,再将临时表与查询主表进行join。

其中要注意的是,因为业务部署使用的是分布式部署,有多个节点,要保证每个临时表在多个节点下也是唯一的。这里采用的方式是使用节点ip+port+IdUtil.objectId()【也可以使用雪花参数,但还是要加上IP与端口才能保持唯一】

示例:

        原SQL(当数组ids的数值过多时,查询效率很慢)

        select
        count(*)
        from t_test_info info
        <where>
            info.status = 0 
            <if test="ids!= null and ids.size > 0 ">
                AND info.id in
                <foreach collection="ids" separator="," open="(" close=")" item="id">
                    #{id}
                </foreach>
            </if>
        </where>

      优化SQL

1、新建临时表xml, 包含创建临时表、临时表新增数据、drop临时表

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.TemporaryTableMapper">

    <update id="createPtIdTempTable">
        drop temporary table if exists ${tableName};
        create temporary table ${tableName}
        (
            pt_id bigint not null
        )
    </update>

    <insert id="batchInsertPtIdTempTableData">
        insert into ${tableName} (id)
        values
        <foreach collection="list" item="item" separator=",">
            (#{item})
        </foreach>
    </insert>

    <delete id="dropTempTable">
        drop temporary table if exists ${tableName};
    </delete>
</mapper>

2、代码优化

    //新建临时表
 String tempTableName = "t_temp_" +HttpUtil.getIpPort()+ IdUtil.objectId();
        temporaryTableMapper.createPtIdTempTable(tempTableName);
        temporaryTableMapper.batchInsertPtIdTempTableData(queryDto.getPtIds(), tempTableName);
    //将临时表名称传入sql

对应sql优化

        select
        count(*)
        from t_test_info info
         join ${tempTableName} temp on info.id = temp.id
        <where>
            info.status = 0 
        </where>

然后再去对列表测试,可以发现查询效率大幅度提升。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Boot ,你可以使用 `@Query` 注解来自定义 SQL 查询语句,在其使用 `IN` 关键字来查询数组内的内容。 假设有一个实体类 `User`,其包含一个属性 `name`,你想要查询所有名字在一个字符串数组 `names` 的用户,可以按照以下步骤进行操作: 1. 在 `UserRepository` 接口定义一个自定义查询方法,使用 `@Query` 注解指定 SQL 查询语句,如下所示: ```java public interface UserRepository extends JpaRepository<User, Long> { @Query("select u from User u where u.name in :names") List<User> findByNames(@Param("names") String[] names); } ``` 在这个方法,我们使用 `in` 关键字来查询 `name` 属性是否在 `names` 数组,`:names` 是一个命名参数,用于接收 `names` 数组作为查询条件。 2. 在 Service 层调用该方法,如下所示: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> findByNames(String[] names) { return userRepository.findByNames(names); } } ``` 在 Service 层,我们直接调用 `UserRepository` 的 `findByNames` 方法即可查询符合条件的用户。 3. 调用 Service 方法进行查询,如下所示: ```java @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/users") public List<User> getUsers(@RequestParam("names") String[] names) { return userService.findByNames(names); } } ``` 在 Controller 层,我们接收前端传入的 `names` 参数,并将其作为查询条件传递给 Service 层进行查询。 以上就是在 Spring Boot 使用数组作为查询条件进行 SQL 查询的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值