- sql优化要先拉取需要优化的语句放入数据库,用expalin查看运行计划,看是否走了索引,如果没有走,查看自己的语句分析没有走索引的原因,并进行语句修改。
- 可以用System.currentTimeMillis()来判断查询语句和for循环的使用时间。
- map的使用,把数据库查询出来的结果封装到map,在通过map.get(key)拿到value值,以此减少循环中和数据库交互的情况。
-
由于在双重for循环使用了数据库交互,导致时间较长优化
优化方案:抽出与数据库交互的部分,用map来封装查询结果,取得时候从map中获取需要的值。
本次优化有两个难点:
- 将普通查询结果封装到map
- 查出来的结果做sum汇总
解决展示:1.将普通查询结果封装到map ,查出所有模板编码以及对应名称,数据库查询语句:
SELECT DISTINCT a.template_code templateCode,a.template_name templateName from message_template a
数据库结果展示:
?
mapper.xml层封装(返回的是list<map<string,string>>),resultType用java.util.Map:
<!--获取所有机构和机构名称 -->
<select id="getdeptCodeAndName"
resultType="java.util.Map">
SELECT DISTINCT a.dept_id deptId,a.`name` deptName from sys_dept a
</select>
mapper层封装:
/**
* 获取所有服务编码和服务名称
* @return
*/
List<Map<Integer,String>> getdeptCodeAndName();
实现类impl调用
//获取全部模板和名称封装到map
List<Map<String, String>> templateCodeAndNameList = countMapper.getTemplateCodeAndName();
Map<String, String> getTemplateNameMap = new HashMap<>();
for (Map<String, String> stringStringMap : templateCodeAndNameList) {
getTemplateNameMap.put(stringStringMap.get("templateCode"),stringStringMap.get("templateName"));
}
封装好的map使用
//上面是数据库交互,下面是直接从map中获取
// sendStaticResp.setTemplateCode(countMapper.getTemplateName(templateCode));
sendStaticResp.setTemplateCode(getTemplateNameMap.get(templateCode));
2.查出来的结果做sum汇总 :每个服务中每个机构的发送总数? ,数据库查询语句:
SELECT
sum(a.total_num) total ,a.dept_id deptId,a.template_code templateCode
FROM
send_static_info a
GROUP BY a.dept_id,a.template_code;
查询结果:
?mapper.xml层封装(返回的是一个封装的对象,字段有templateCode,deptId,total):
<!--查出所有所有服务中所有机构对应的发送总数 -->
<select id="getALLCount"
resultType="com.sinosoft.liscloud.sms.api.vo.SendStaticSumResp">
SELECT
sum(a.total_num) total ,a.dept_id deptId,a.template_code templateCode
FROM
send_static_info a
GROUP BY a.dept_id,a.template_code;
</select>
mapper层封装:
/**
* 查出所有所有服务中所有机构对应的发送总数
* @return
*/
List<SendStaticSumResp> getALLCount();
实现类impl调用:期间使用了System.currentTimeMillis()来判断查询语句和for循环的使用时间,
将查询结果封装到了两个map,getTotalMap封装了机构编号+服务编码,保证map中的key的唯一,外层循环为了查询不重复的服务编码,内层循环机构编码,在内层循环时通过传入的编码和机构编码,获取到查询结果中的total数,getSumTotalMap主要是做汇总使用,传入机构编码,为空直接从结果集获取total数,不为空从getTotalMap中通过机构编码查出来总数追加
//查出所有所有服务中所有机构对应的发送总数
List<SendStaticSumResp> sumList = new ArrayList<>();
long l = System.currentTimeMillis();
sumList = countMapper.getALLCount();
long l2 = System.currentTimeMillis();
System.out.println("查询语句-----------------------------------"+ (l2-l) );
//将k和总数封装以及k和部门名称封装到不同的map中
Map<String, Integer> getTotalMap = new HashMap<>();
Map<String, Integer> getSumTotalMap = new HashMap<>();
long currentTimeMillis = System.currentTimeMillis();
for (SendStaticSumResp sendStaticSumResp : sumList) {
if (sendStaticSumResp.getDeptId()==null){
sendStaticSumResp.setDeptId("");
}
if (sendStaticSumResp.getTemplateCode() ==null){
sendStaticSumResp.setTemplateCode("");
}
getTotalMap.put(sendStaticSumResp.getDeptId()+sendStaticSumResp.getTemplateCode(),sendStaticSumResp.getTotal());
getSumTotalMap.put(sendStaticSumResp.getDeptId(),
getSumTotalMap.get(sendStaticSumResp.getDeptId())==null? sendStaticSumResp.getTotal()
: sendStaticSumResp.getTotal()+getSumTotalMap.get(sendStaticSumResp.getDeptId()) );
}
long currentTimeMillis2 = System.currentTimeMillis();
System.out.println("查询for循环-----------------------------------"+(currentTimeMillis2-currentTimeMillis));
使用map
if ("sum".equals(templateCode)){
templateCode = null;
sendStaticResp.setTemplateCode("汇总");
for(int i=0;i<deptIdList.size();i++) {
String sumDeptId = deptIdList.get(i);
// Integer sumTotal = countMapper.getCount(sumDeptId,templateCode);
Integer sumTotal= getSumTotalMap.get(sumDeptId);
if(sumTotal ==null) {
sumTotal=0;
}
else {
for (int i=0;i<deptIdList.size();i++) {
String deptId = deptIdList.get(i);
// String deptName = countMapper.getDeptName(deptId);
String deptName = getDeptNameMap.get(deptId);
Integer total = 0;
Map<String, Integer> deptCount = new HashMap<>();
// total = countMapper.getCount(deptId, templateCode);
total = getTotalMap.get(deptId+templateCode);
|