这两天看了一下sql explain,似乎工作中我们不太重用这个命令。(但是某些场合又很重要,例如面试)。
之所以突然想起来拿出来说说,就是前两天产品经理跑过来跟我讲了一个需求:把某个客户这一年的库存出入库报表导出来。
我们wms系统是支持报表查询及导出功能的,但是仅支持三个月的查询,所以系统无法满足此项需求。
看一下sql:
select wh.name '仓库名称',customer.name'所属货主',sku.sku_name '商品名称',sku.sku_code '商品编码',unit.name '单位',
temp.startNum '期初库存',temp.addNum '入库',temp.subNum '出库',temp.endNum '结存', temp.reportTime '统计日期'
from (SELECT id , store_id storeId , customer_id customerId , sku_id skuId,
SUM(add_num) addNum,
SUM(`sub_num`) subNum,
SUBSTRING_INDEX(GROUP_CONCAT( start_num ORDER BY report_time ), ',',1) startNum,
SUBSTRING_INDEX(GROUP_CONCAT( end_num ORDER BY report_time ), ',',-1) endNum ,
report_time reportTime, create_time createTime
from (
select * from wms.warehouse_inventory_report
where store_id=349956600930598912 and customer_id=349956601031262208
order by
report_time
) a
group by
customer_id,store_id,sku_id) temp
inner join oms.sku sku on sku.id=temp.skuId
inner join oms.warehouse wh on wh.id=temp.storeId
inner join oms.unit_sku us on us.sku_id=temp.skuId and us.level=1
inner join oms.unit unit on unit.id=us.unit_id
inner join oms.customer customer on customer.id=temp.customerId;
inner join,多个基础数据表。
目前程序中我们都不会写这么多的连接,仅仅把需要的库存数据warehouse_inventory_report查出来,然后通过缓存查询仓库名称、货主名称、商品编码、
单位。(当然wms系统查询时会对库存数据进行处理,能转二级单位就会转二级显示,即优先显示大包装)。
explain 查看执行计划:
explain 主要看两项指标:type和extra。
type:表示MySQL在表中找到所需行的方式,又称“访问类型”。
常用的类型有: ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)。
extra:该列包含MySQL解决查询的详细信息。
possible_keys:指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用(
key: key列显示MySQL实际决定使用的键(索引),必然包含在possible_keys中
我们可以该查询语句 type有all,并且Using filesort等。
显然需要优化。
unit_sku 在sku_id加上索引。
warehouse_inventory_report在 customer_id,store_id,sku_id 加上联合索引,report_time加上索引。
再看下执行计划: