如下图所示的这种列表应该是系统里最常见的了。随着数据的增长,查询的速度也将越来越慢,那就需要优化了。
数据库使用的是mysql, 分页命名用的是mybatis plus 的paging插件。
今天重点是讲怎么去优化SQL。
1:Mapper 代码
<select id="getPages" resultType="com.ly.mp.swcas.main.entities.Retrospect">
SELECT
r.*,
v.LOOKUP_VALUE_NAME,
v.LOOKUP_VALUE_CODE,
s.VIN
FROM
t_swcas_bu_retrospect As r
LEFT JOIN t_swcas_db_lookup_value As v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE AND v.COMM_TYPE_CODE = 'swcas_trace_no'
and r.IS_ENABLE=1
LEFT JOIN t_swcas_bu_sale As s ON r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER and s.IS_ENABLE=1
<where>
<if test="sapOrderNo != null and sapOrderNo !='' ">
and r.SAP_ORDER_NO = #{sapOrderNo}
if>
<if test="mesProductionNo != null and mesProductionNo !=''">
and r.MES_PRODUCTION_NO = #{mesProductionNo}
if>
<if test="retrospectPartNo != null and retrospectPartNo !='' ">
and r.RETROSPECT_PART_NO = #{retrospectPartNo}
if>
<if test="vin != null and vin !='' ">
and s.VIN = #{vin}
if>
<if test="lookUpValueName != null and lookUpValueName !='' ">
and LOOKUP_VALUE_NAME = #{lookUpValueName}
if>
where>
select>
2:使用mybatis plus分页会产成两个脚本(不使用任务条件的情况下)。分别是:
1):页数据查询
SELECT
r.*,
v.LOOKUP_VALUE_NAME,
v.LOOKUP_VALUE_CODE,
s.VIN
FROM
t_swcas_bu_retrospect As r
LEFT JOIN t_swcas_db_lookup_value As v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE AND v.COMM_TYPE_CODE = 'swcas_trace_no'
and r.IS_ENABLE=1
LEFT JOIN t_swcas_bu_sale As s ON r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER and s.IS_ENABLE=1 limit 10,10
2):总数查询
SELECT
count(1)
FROM
t_swcas_bu_retrospect AS r
LEFT JOIN t_swcas_db_lookup_value AS v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE
AND v.COMM_TYPE_CODE = 'swcas_trace_no'
AND r.IS_ENABLE = 1
LEFT JOIN t_swcas_bu_sale AS s ON r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER
AND s.IS_ENABLE = 1;
3):耗时结果
1 页数据查询很快,耗时0.003秒。
2 总数查询慢,耗时8秒。
数量为:80万。
结果如用户反馈一样,非常慢。。
1:业务表分析
t_swcas_bu_retrospect 零件追溯表(开发环境80W数据,生产500W)
t_swcas_db_lookup_value 键值表 (数据量1000)
t_swcas_bu_sale 销售表(开发环境 30W, 生产100万)
1:t_swcas_bu_retrospect 、t_swcas_bu_sale 两个大表关联,实际上只为了取销售表里的一个字段。优化:使用子查询处理
。
2:与值列表关联使用inner join。确认是能一一对应上的。把r.IS_ENABLE = 1
放在 where 之后。
3:第2步去掉了 t_swcas_bu_sale 关联,那么 t_swcas_bu_sale 对应的条件也要处理。如下
and r.SAP_ORDER_NO in (select s.PLANNED_ORDER_NUMBER from t_swcas_bu_sale s where s.vin = #{vin})
结体SQL优化如下:
<select id="getPages" resultType="com.ly.mp.swcas.main.entities.Retrospect">
SELECT
r.*,
v.LOOKUP_VALUE_NAME,
v.LOOKUP_VALUE_CODE,
v.EXT_COL01 AS LOOKUP_VALUE_EN_NAME,
(select s.VIN from t_swcas_bu_sale s where s.IS_ENABLE=1 and r.SAP_ORDER_NO = s.PLANNED_ORDER_NUMBER limit 1 ) as VIN
FROM
t_swcas_bu_retrospect As r
inner JOIN t_swcas_db_lookup_value As v ON r.RETROSPECT_PART_NO = v.LOOKUP_VALUE_CODE AND v.COMM_TYPE_CODE = 'swcas_trace_no'
where r.IS_ENABLE=1
<if test="sapOrderNo != null and sapOrderNo !='' ">
and r.SAP_ORDER_NO = #{sapOrderNo}
if>
<if test="mesProductionNo != null and mesProductionNo !=''">
and r.MES_PRODUCTION_NO = #{mesProductionNo}
if>
<if test="retrospectPartNo != null and retrospectPartNo !='' ">
and r.RETROSPECT_PART_NO = #{retrospectPartNo}
if>
<if test="vin != null and vin !='' ">
and r.SAP_ORDER_NO in (select s.PLANNED_ORDER_NUMBER from t_swcas_bu_sale s where s.vin = #{vin})
if>
<if test="lookUpValueName != null and lookUpValueName !='' ">
and LOOKUP_VALUE_NAME = #{lookUpValueName}
if>
order by r.created_date desc
select>
1:根据排序字段创建索引
create index ix_t_swcas_bu_retrospect_CreatedDate on t_swcas_bu_retrospect (created_date desc)
2:根据关联字字段创建索引
create index ix_t_swcas_bu_retrospect_RETROSPECT_PART_NO on t_swcas_bu_retrospect (RETROSPECT_PART_NO )