程序员(小李):负责某核心业务功能的开发。
运维(老张):负责系统的部署和监控。
业务方(李总):负责业务需求和上线进度,强调快速扩张。
场景:会议室中,小李、老张和李总正在讨论全境派送运单分拣问题出错的解决方案。
李总(焦急地):小李,老张,这次全境派送的问题很严重啊!面单上的条码和第三方跟踪单号对不上,货物到了中心后,分拣直接瘫痪了。我们的业务扩张速度这么快,这个问题必须马上解决!
小李(认真地):李总,我已经分析了问题的根源。主要是在分拣总包预报的接口中,查询第三方跟踪单号和第三方面单号的SQL关联查询性能太慢,导致数据匹配失败。
老张(点头):对,我也监控到了这个问题。两张大表的关联查询,数据量太大,索引直接失效了。小李,你有什么解决方案吗?
小李:是的,我做了以下优化:
将两张大表的关联查询拆分成两个SQL查询,先查一次表,再组合数据,避免索引失效。
第三方面单号是新加字段,生产数据中很多是空值,导致索引失效。我设置了默认值为空字符串,增加了字段的基数,提升了索引选择性。
发现IN子句中的值在100-200左右时,索引才会生效。所以我将查询分组,每次IN 200条,用上索引提速。
老张(赞许地):这个思路不错!我之前也遇到过类似的问题,IN子句的值太多,优化器直接选择全表扫描了。你这种分批次查询的方式,确实能有效提升性能。
李总(稍微放松):听起来不错,但我们的业务扩张速度很快,数据量会越来越大。这些优化能支撑多久?
小李:李总,这些优化是经过充分测试的,能够支撑当前的数据量。未来如果数据量继续增长,我们可以考虑进一步优化,比如引入缓存机制或者分库分表。
老张:对,我这边也会加强监控,确保系统的稳定性。如果有性能瓶颈,我会第一时间通知小李。
李总(满意地):好,那你们抓紧时间上线这些优化。我们的业务不能停,分拣问题必须尽快解决。
小李:明白,李总。我会尽快完成代码优化和测试,确保不影响业务。
老张:我这边也会配合小李,做好部署和监控工作。
李总(站起身):好,那就辛苦你们了!希望这次优化能彻底解决问题,让我们的业务继续快速扩张!
产生背景
对于全境派送的运单,分拣和派送需要得到面单,面单信息包含:,
1.运单信息;
2.第三方的跟踪单号,
3.其他派送信息
功能上线之后发现:
1.面单上条码跟第三方的跟踪单号对不上;
2.货物到了中心后,中心需要支持扫描第三方,信息不对,没办法分拣;
问题发生节点,分拣总包预报的接口。
逻辑流程:
TrackingNumber匹配运单号——
CustomerNumber匹配运单号——
CustomerNumber匹配参考号——
CustomerNumber匹配第三方跟踪号——
CustomerNumber匹配第三方面单号——
查询第三方跟踪单号和第三方面单号的SQL关联查询性能慢。
导致了问题的出现。
解决过程
1:两张大表的关联查询,数量量太大,索引失效。
解决方式:代码改为查两次表,再组合数据;
2:单独查转第三方表,由于第三方面单号为新加字段,生产数据新字段都是空,即便有索引,索引也会失效
解决方式:第三方面单号设置默认=值''空值,索引也不生效
给到dba对应的sql语句,填充历史数据的默认值。
3:生产执行SQL发现IN子句中的值在100-200左右的时候,索引才会生效
解决方式:每次 IN 200条用上索引提速
解决方案
1:两张大表的关联查询分开,一个SQL拆分成两个SQL查询
2:之前SQL查询按照1000条分组多次查询,调整成一组的数量做成可配置的,200条一组查询
3:新加字段第三方面单号设置默认值,增加大表新字段的基数,增加索引选择性
经验总结
mysql数据库索引不包含 NULL 值, 使用 in 条件时,全是 NULL 的字段选择性为 0,索引完全失去筛选价值
优化器可能认为全表扫描比使用索引更高效
1.使用模糊匹配(如 LIKE %xx 或 LIKE %xx%)时,索引将失效。
2.在查询条件中对索引列应用函数会导致索引失效。
3.对索引列进行表达式计算同样无法使用索引。
4.当字符串与数字进行比较时,MySQL会自动将字符串转换为数字,这种隐式类型转换会导致索引失效。
5.联合索引的使用必须遵循最左匹配原则,否则会导致索引失效。
6.在 WHERE 子句中,如果 OR 前的条件是索引列而 OR 后的条件不是,索引也会失效。