SELECT count(*) FROM spu s1 WHERE EXISTS ( SELECT * FROM sku s2 INNER JOIN mall_sku s3 ON s3.sku_id = s2.id WHERE s2.spu_id = s1.id AND s2.status = 1 AND NOT EXISTS ( SELECT * FROM supplier_sku s4 WHERE s4.mall_sku_id = s3.id AND s4.supplier_id = 123456789 AND s4.status = 1 ) )这条SQL的含义是统计id=123456789的供应商,未发布的spu数量是多少。这条SQL的耗时竟然达标了8s,必须要做优化了。我首先使用explain关键字查询该SQL的执行计划,发现spu表走了type类型的索引,而sku、mall_sku、supplier_sku表都走了ref类型的索引。也就是说,这4张表都走了索引。不是简单的增加索引,就能解决的事情。
从目前看,这种写性能有瓶颈。因此,我做出了第一次优化。
使用join + group by组合,将sql优化如下:
SELECT count(*) FROM ( select s2.spu_id from spu s1 inner join from sku s2 inner join mall_sku s3 on s3.sku_id=s2.id where s2.spu_id=s1.id ans s2.status=1 and not exists ( select * from supplier_sku s4 where s4.mall_sku_id=s3.id and s4.supplier_id= ) group by s2.spu_id ) a由于spu_id在sku表中是增加了索引的,因此group by的性能其实是挺快的。这样优化之后,sql的执行时间变成了2.5s。性能提升了3倍多,但是还是不够快,还需要做进一步优化。
SELECT count(*) FROM ( select s2.spu_id from spu s1 inner join from sku s2 inner join mall_sku s3 on s3.sku_id=s2.id where s2.spu_id=s1.id ans s2.status=1 and s3.id not IN ( select s4.mall_sku_id from supplier_sku s4 where s4.mall_sku_id=s3.id and s4.supplier_id= ) group by s2.spu_id ) a这样优化之后,该sql的执行时间下降到了0.7s。之后,我再用explain关键字查询该SQL的执行计划。发现spu表走了全表扫描,sku表走了eq_ref类型的索引,而mall_sku和supplier_sku表走了ref类型的索引。可以看出,有时候sql语句走了4个索引,性能未必比走了3个索引好。多张表join的时候,其中一张表走了全表扫描,说不定整个SQL语句的性能会更好,我们一定要多测试。