一次SQL优化
原SQL
语句为:
根据tenantId、skuNo、ownerNo批量查询商品属性
<select id="queryBatchSkuStoreAttrs" parameterType="java.util.List"
resultMap="BaseResultMap">
<foreach collection="list" item="item" index="index" separator=" union ">
SELECT
*****
FROM ssa JOIN
ssi
ON #####
AND #####
AND ###
WHERE ssa.xxx = #{item.xxx,jdbcType=VARCHAR} AND ssa.yyy = #{item.yyy,jdbcType=VARCHAR}
AND ssa.zzz = #{item.zzz,jdbcType=VARCHAR}
</foreach>
</select>
很明显该SQL
存在大量拼接重复语句的问题,在一个大循环中重复调用造成性能消耗。而且随着List的增大,生成的SQL
语句也会非常冗长。
优化方式: 将原SQL
改为in
条件查询,减少查询次数。
修改后的SQL
为:
<select id="queryBatchSkuStoreAttrs" parameterType="java.util.List" resultMap="BaseResultMap">
SELECT
*****
FROM ssa JOIN
ssi
ON #####
AND #####
AND ###
WHERE ssa.xxx IN
(<foreach collection="list" item="item" index="index" separator=",">
#{item.xxx,jdbcType=VARCHAR}
</foreach>)
AND ssa.yyy IN
(<foreach collection="list" item="item" index="index" separator=",">
#{item.yyy,jdbcType=VARCHAR}
</foreach>)
AND ssa.zzz IN
(<foreach collection="list" item="item" index="index" separator=",">
#{item.zzz,jdbcType=VARCHAR}
</foreach> )
</select>
但是这样得到的结果是以查询条件的笛卡尔积
而生成的,其中必然包含不属于原查询条件的结果,因此需要对得到的结果集进行去重处理,得到与原结果集相匹配的结果集和。
众所周知,set
具有无序、不重复 的特点。因此,可以利用这个特点对结果集List中的元素与查询条件集做对比进行筛选,若结果集的字段能插入查询条件集生成的set
中,说明该条记录与原查询条件不匹配,也就是需要删除的记录。示例代码如下:
List<SkuStoreAttr> skuStoreAttrsNew = skuStoreAttrDao.queryBatchSkuStoreAttrs(store);
//使用set去除多余的信息
Set<String> keySet = new HashSet<>();
store.forEach(skuStoreAttr -> keySet.add(makeKey(skuStoreAttr)));
for(Iterator<SkuStoreAttr> iterator = skuStoreAttrsNew.iterator();iterator.hasNext();){
String key = makeKey(iterator.next());
if(keySet.add(key)){
iterator.remove();
}
}
其中,makeKey()
方法提取dto中的特征字段作为每个元素的唯一标识,用来标记每一个dto
在删除重复元素时,使用迭代器Iterator
进行遍历处理,保证List中的元素可以被正确的删除。遍历之后便可以得到无重复的List。