1. 程式人生 > 實用技巧 >0058、按月分組查詢近12個月的資料(效能優化)

0058、按月分組查詢近12個月的資料(效能優化)

優化思路:

1)原功能邏輯為for迴圈12次,將年月做為引數去資料庫查詢12次資料

2)優化思路:儘量將資料一次性從資料庫中查詢出來,通過java進行邏輯處理,減少和資料庫互動次數,提升效能

java方法如下:

public CompanyCountDTO getCompanyCount() {
long start1 = System.currentTimeMillis();
List<CountDTO> countList = new ArrayList<>();
CompanyCountDTO dto = new CompanyCountDTO();
Calendar instance = Calendar.getInstance();
int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH) + 1;

int y = year - 1;
int m = month + 1;
//初始化12個月點日期
if (m > 12) {
y = y + 1;
m = m - 12;
}
for (int i = 0; i < 12; i++) {
CountDTO counDto = new CountDTO();
String data = String.valueOf(m) + "月";
counDto.setDate(data);
counDto.setCount(companyMapper.selectCountCompanycode(m, y));
countList.add(counDto);
m++;
if (m > 12) {
y++;
m -= 12;
}

}
long end1 = System.currentTimeMillis();
long cost1 = end1 -start1;
log.info("方式1查詢耗時==========================================:" + cost1);
int y2 = year - 1;
int m2 = month + 1;
//初始化12個月點日期
if (m2 > 12) {
y2 = y2 + 1;
m2 = m2 - 12;
}
String m2Str = m2<10?("0"+m2):(""+m2);
// 從ec_order表查詢近12月的全部資料
List<MemberIdAndMonthDTO> memberIdAndMonthDTOList = companyMapper.selectMemberIdFor12Months(y2 + "" + m2Str);
//取出memberId並去重形成集合
List<String> memberIds = memberIdAndMonthDTOList.stream().map(e -> e.getMemberId()).distinct().collect(Collectors.toList());
List<CompanyCodeDTO> companyCodeDTOList = null;
if(org.apache.commons.collections.CollectionUtils.isNotEmpty(memberIds)){
companyCodeDTOList = companyMapper.selectDistinctCompanyByAccountVip(memberIds);
}
//按月分組
Map<String, List<MemberIdAndMonthDTO>> monthDTOMap = memberIdAndMonthDTOList.stream().collect(Collectors.groupingBy(e -> e.getOrderMonth()));
String tmpYearMonth = "";
List<CountDTO> countList2 = new ArrayList<>();
for (int i = 0; i < 12; i++) {
tmpYearMonth = y2 + "" + (m2<10?("0"+m2):(""+m2));
CountDTO counDto = new CountDTO();
String data = String.valueOf(m2) + "月";
counDto.setDate(data);
List<MemberIdAndMonthDTO> memberIdAndMonthDTOS = monthDTOMap.get(tmpYearMonth);
List<String> memberIdList = new ArrayList<>();
if(org.apache.commons.collections.CollectionUtils.isNotEmpty(memberIdAndMonthDTOS)){
memberIdList = memberIdAndMonthDTOS.stream().map(e->e.getMemberId()).collect(Collectors.toList());
}
final List<String> memberIdListFinal = memberIdList;
long count = 0;
if(org.apache.commons.collections.CollectionUtils.isNotEmpty(memberIdList) && org.apache.commons.collections.CollectionUtils.isNotEmpty(companyCodeDTOList)){
//由於可能存在兩條資料,companyCode+pCompanyCode相同,但是accountVip不同,此處統計時,應該沒統計為一條資料
count = companyCodeDTOList.stream().filter(e -> memberIdListFinal.contains(e.getAccountVip()))
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getCompanyCode() + ";" + o.getPCompanyCode()))), ArrayList::new))
.size();
}
counDto.setCount((int) count);
countList2.add(counDto);
m2++;
if (m2 > 12) {
y2++;
m2 -= 12;
}

}

long end2 = System.currentTimeMillis();
long cost2 = end2 -end1;
log.info("方式2查詢耗時=======================================:" + cost2);
log.info("方式1查詢到的資料為=================================:");
for (CountDTO countDTO : countList) {
log.info("月份:" +countDTO.getDate() + ",數量:" + countDTO.getCount());
}
log.info("方式2查詢到的資料為=================================:");
for (CountDTO countDTO : countList2) {
log.info("月份:" +countDTO.getDate() + ",數量:" + countDTO.getCount());
}



dto.setCountList(countList);
return dto;
}

用到的sql語句如下:

1)

<select id="selectCountCompanycode" resultType="java.lang.Integer">
select count(*)
from
(select distinct COMPANY_CODE,PCOMPANY_CODE
from ESGCC_DBUSER.EC_TRAVEL_VIP_INFO
where ACCOUNT_VIP in
(select MEMBER_ID
from ESGCC_DBUSER.EC_ORDER
where
TO_CHAR(ORDER_TIME,'yyyy')=#{year}
and TO_CHAR(ORDER_TIME,'mm')=#{month}))

</select>

2)

<select id="selectMemberIdFor12Months" resultType="com.dingxianginc.audit.pojo.oracle.purchase.zcompanycode.dto.MemberIdAndMonthDTO">
select MEMBER_ID memberId,TO_CHAR(ORDER_TIME,'yyyyMM') orderMonth
from ESGCC_DBUSER.EC_ORDER
where
TO_CHAR(ORDER_TIME,'yyyyMM') <![CDATA[ >= ]]> #{yearMonth}
</select>

3)

<select id="selectDistinctCompanyByAccountVip" resultType="com.dingxianginc.audit.pojo.oracle.purchase.zcompanycode.dto.CompanyCodeDTO">
select COMPANY_CODE companyCode,PCOMPANY_CODE pCompanyCode,ACCOUNT_VIP accountVip
from ESGCC_DBUSER.EC_TRAVEL_VIP_INFO
where ACCOUNT_VIP in
<foreach collection="memberIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>