一个线上问题引起的思考,为何最左前缀原则?

中秋节前夕,立刻就要准备放假回家去畅游王者峡谷的小涛收到了报警,某mq消息积压几十万并且正在一直往上涨,看了下依赖的接口和hbase无问题,发现mysql读写速度很慢,因而乎看了下mysql机器负载,cpu高达百分之85,使用showprocesslist,查询当前运行的sql,发现并无很慢的sql,可是发现有以下sql在大量执行,html

可是查询速度并非很慢,根据订单号去查了一下该订单商品,发现此订单买的商品是买1赠5,可怕的是这我的买了1万套,对于这样的场景业务上会存5万条数据做为主赠关系,说白了,就是消费这个订单的消息时,要去查询5万次。因为消费mq超时时间只有3秒,没等5万次查询完成去作业务处理就超时了,而后消息进行重试,又被其余实例消费,继续查询5万次,查询了下该表索引,发现只有orderId 这个字段有索引,全部查询其余字段的时候还要扫表,致使cpu升高,读写变慢,消息积压,临时方案,修改了下mq超时时间,放次消息消费过去,而后开始着手,从新建索引,而后就有了以下的分析。mysql

这张表除了这个查询语句之外,还有查询条件为(orderIdserviceId),(orderIdskuUuid)的语句,那么如何建索引才更合理呢, 初始版本一个联合索引(orderIdserviceId,skuUuid),可是在(orderIdskuUuid)时skuUuid没法使用索引,依然会有以前的问题,第二个版本建2个联合索引(orderIdserviceId, skuUuid),(orderId, skuUuid)这样能够都使用到索引了。那么问题来了,为何索引要有最左前缀,为何中间少了一个字段后面的就不能使用索引了呢? 好比原表中的数据是这样的:sql

创建了(orderIdserviceId,skuUuid)复合索引以后,索引文件数据应该是这样的:post

从全表来看orderId是有序的,而serviceId和skuUuid是相对有序的,因此若是没有orderId,直接访问serviceId或skuUuid,那确定是无序的,因此也就用不到索引了,因此联合索引就相似于闯关同样,要一关一关的来,断开则后面的都没法使用到索引。ui

留下几个感受比较好的连接已备后面复习,你们也能够看看。.net

www.cnblogs.com/rjzheng/p/9… 烟哥牛逼!code

juejin.im/post/5d23ef…cdn

blog.csdn.net/u014029277/…htm

blog.csdn.net/zly9923218/…blog

相关文章
相关标签/搜索