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
繰り返し文のスプライシングの問題の多くは、性能の消費を引き起こして大きなループを繰り返し呼び出しで、そこにあります。そして、リストが増加すると、結果の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
それが持っている障害を、重複しない機能を。したがって、この機能フィールドは、生成されたクエリセットの結果セットの中に挿入することができれば、比較は、スクリーニングされない結果セットリストクエリセット内の要素のために利用することができる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
リスト要素を確実にするために処理を横断するように適切に除去することができます。横断した後には、リストのない繰り返しになることはできません。