1、联合索引失效
项目上有个第三方账号绑定模块,对应的有张第三方账号记录表:
- 表中有记录设备账号相关信息字段,如 app_id;
- 有记录第三方平台账号的字段:weixin_id、qq_id、apple_id 等;
有次搞活动促销的时候,日志提示第三方账号登录这块出现了慢查询日志。那么我就去排查,慢查询日志提示的 SQL 如下:
select * from account
where weixin_id ='xxx' or qq_id ='xxx' or app_id = 'xxx';
线上的数据表有五十多万条,然后我本地拉取了开发环境的数据,然后对数据量进行了模拟,最终执行该 sql 时发现耗时 1.5 秒。这结果还是我本地电脑跑出来的,线上并发的环境下,时间已经超过2、3秒了。
然后我用 explain
命令对这条 sql 进行分析,结果发现命中的索引字段 key、key_len 都为 null,扫描行数 rows 为全表行数。很明显,这是在执行过程没有使用索引导致了全表查询。
然后我查看了一下表的建索引情况,发现对应的查询字段是有建索引的:
KEY idx_union_id(weixin_id, qq_id, apple_id);
索引为联合索引,联合索引失效的场景无非就是没有遵循最左匹配原则,但我对比了一下索引的个数、顺序都和执行的 SQL 一样,虽然执行的 SQL 使用的是 or
关键字来连接字段,但它遵循了联合索引的最左匹配原则还不至于导致索引失效。
但我仔细对比了字段发现,执行的 sql 语句中有个字段 apple_id 写成了 app_id。这下就真相大白了,app_id 字段没有加索引,所以在 or 条件查询下执行就导致了索引失效而引发全表扫描。
最后更正过来后再次测试,结果耗时只有零点几秒了。