在测试压测过程中发现有一个统计接口qps只有3.4/sec,但是脚本比较简单,只是进行了count和sum,也没有特别复杂的查询条件,经过本地调试,发现把脚本单独拉到控制台执行只要600毫秒,并且本地调用接口前9次都很快,第十次开始脚本就要执行2秒,重启项目之后还是一样。
脚本示例
select
count(*) as item_no_num,
COALESCE(sum(m.sum_insured),0) as sum_insured_sum,
COALESCE(sum(m.sum_priceTax_total),0) as sum_priceTax_total_sum
from policy_list m
where m.state = '1'
and st_contains(st_geometryfromtext(#{range},4326),m.gemo)
<choose>
<when test='dataDate != null and dataDate != ""'>
AND m.start_date <![CDATA[<=]]> #{dataDate}
AND m.end_date <![CDATA[>=]]> #{dataDate}
</when>
<otherwise>
AND m.start_date <![CDATA[<=]]> NOW()
AND m.end_date <![CDATA[>=]]> NOW()
</otherwise>
</choose>
处理过程
在百度查了一下,发现有挺多帖子说了这个问题,解决方案一般分为三种
1、将传参改为java.util.Date
2、将传参改为java.sql.Date
3、将#{date}改为${date}
第一个和第二个方法都试了没有作用,第三个方法可以正常执行,网上说是mybatis的预编译有问题,改为$后就不会预编译了而是直接拼接到sql中。
但是这样有一个问题,由于date是前端传过来的,所以会有SQL注入的风险,于是在执行脚本之前加了一个日期转换,如果前端传过来的日期字符串可以正常转换为Date就没问题,否则就会报错。
代码如下:
@Override
public SearchPolicyItemCountVo searchPolicyItemByGeometry(SearchItemNoPositionListCommonDTO searchDTO, String companyCode) {
// 对日期格式做校验
String dataDate = searchDTO.getDataDate();
if (StrUtil.isNotBlank(dataDate)) {
DateUtil.parse(dataDate);
}
return guMainMapper.searchPolicyItemByGeometry(
searchDTO.getRiskClassList(),
searchDTO.getRiskCodeList(),
searchDTO.getPolygon(),
dataDate,
searchDTO.getSearchCompanies(),
companyCode);
}
最终脚本如下:
select
count(*) as item_no_num,
COALESCE(sum(m.sum_insured),0) as sum_insured_sum,
COALESCE(sum(m.sum_priceTax_total),0) as sum_priceTax_total_sum
from policy_list m
where m.state = '1'
and st_contains(st_geometryfromtext(#{range},4326),m.gemo)
<choose>
<when test='dataDate != null and dataDate != ""'>
AND m.start_date <![CDATA[<=]]> '${dataDate}'
AND m.end_date <![CDATA[>=]]> '${dataDate}'
</when>
<otherwise>
AND m.start_date <![CDATA[<=]]> NOW()
AND m.end_date <![CDATA[>=]]> NOW()
</otherwise>
</choose>
由于没有找到其他更好的方法, 只能先保证项目先能正常运行