通过阿里云监控sql的发现,刚上线的sql有性能问题,然后就查这是什么原因导致的
由于这个sql很长,关联了很多表,直接explain解释执行过程,发现有个表是全表扫描
通过sql我们发现,docId的索引是有的,为什么还是全表扫描呢?而且扫描的行数比单表的行数还多,这就很是不解,有索引为啥索引走不了呢?
刚开始以为是关联驱动表的问题,因为inner join 时,mysql会将有索引的表选为被驱动表,由于原来用的left join,改成了inner join,发现还是没有啥效果,并没有什么卵用
这就让我百思不得其解,然后我就写了如下sql,验证索引是否生效
select * from doc_org_relation where node_id = 116119;
得到的explain解释却是这样的
奇怪为什么还是全表扫描,node_id我也有索引的,为什么是全表扫描,这彻底毁了我sql的三观啊,为啥没走索引呢?
后来看了一眼表设计,发现问题了,由于表设计node_id为varchar类型,然后查询的时候,在某种情况下会传Integer类型过来,导致查询的sql条件是int类型的,查询类型和字段类型不匹配,导致添加的索引失效
于是将sql调整为
explain select * from doc_org_relation where node_id = '116119';
然后再查看执行过程,发现走索引了,至此,问题解决
总结:
- 保证被驱动表的join字段已经被索引
- left join 时,选择小表作为驱动表,大表作为被驱动表
- inner join 时,mysql会自己帮你把小结果集的表选为驱动表
- 子查询尽量不要放在被驱动表,有可能使用不到索引
- 能够直接多表关联的尽量直接关联,不用子查询
- 查询条件时,如果表字段类型和查询时条件不一致,尽管查询数据没问题,但是会导致查询的条件索引失效