前几天有个慢sql问题,场景是导入导出,,这个表有大概2亿多的数据,需要加索引优化,表和字段已脱敏。,原sql大概是这样:
select * from object_range force index(idx_obj_no_id) where type = 1 and biz_type = 1 and obj_no = 123 order by id limit 1000,500
可以看到有三个查询字段type,biz_typ,objec_no,原来的查询force index走了obj_no和id的联合索引,但是由于单个object_no下的行数还是会去到几十万行,所以还是慢查询了。
按照我之前的理解,组合索引是会自动加上id的,所以直接在生产提了变更把这三个查询字段怼到一起建了一个联合索引idx_type_biz_type_obj_no。然后修改sql去掉了force_index去跑了一下explain
-- 修改后的sql不用force_index时间0.015s
select * from object_range where type = 1 and biz_type = 1 and obj_no = 123 order by id limit 1000,500
-- 走了新建的索引idx_type_biz_type_obj_no
explain select * from object_range where type = 1 and biz_type = 1 and obj_no = 123 order by id limit 1000,500
非常满意,然后直接发布。
不幸的是生产还是有同样的慢sql,把sql拉下来发现在特定参数下去explain,这条sql会走主键索引,为啥会走primary索引呢。
首先,一条sql在mysql经过分析器,优化器,执行器,再会到存储引擎etc。
请教同事后发现,组合索引确实会加上id,这点确实没记错,但让人裂开的原来这是在存储层那里。对于mysql优化器来说并不知道这条索引加上了id。
所以在对sql进行分析优化的时候,尤其是涉及到排序,可能mysql优化器觉得会出现filesort所以用主键id索引会好一点,因为优化器并不知道这个索引上有id,所以分析的时候不会考虑。。。
然后对sql再次修改走了强制索引发布,慢sql没有了。
explain select * from object_range index(idx_type_biz_type_obj_no) where type = 1 and biz_type = 1 and obj_no = 123 order by id limit 1000,500
回到最开始的时候,理解了为什么最开始这条sql要加idx_obj_no_id索引。所以下次加联合索引还是老老实实在最后把id加上,既没有什么损失,还会有意外收获。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/vipshop_fin_dev/article/details/125139713
内容来源于网络,如有侵权,请联系作者删除!