文章摘要(AI生成)
MySQL在索引使用时,通常会将数据最小的字段放在前面,以最能确定结果的字段为主,以减小检索范围。在查询过程中,MySQL会自动调整字段顺序以优化索引顺序。举例说明了在查询指令表中某一指令在最近3个月未完成结果时,如何通过优化索引和缩小查询范围来提高查询效率。在多条件查询中,MySQL会选择扫描行数最少的索引,以减少查询时间。通过调整索引顺序、添加联合索引或缩小查询范围等方式,可以有效提高查询效率。
mysql在索引使用的时候一般都会把数据最小的字段放前面,也就是最能确定结果的字段,因为索引的第一个字段的检索范围是最小的,然后根据可以确定的数据范围的大小依次排序.这个时候不要担心sql里使用字段的顺序是不是和索引里一样,mysql在查询的时候会自动调整顺序优化成和索引一样的顺序.
场景应用
实际应用中,假设我们有一张指令的表,存储不同调用系统的通讯指令。我们需要坐一个巡检来查询某一指令在最近3个月的未完成的结果。
涉及的表结构为:
为了巡检我们需要定位按时间范围确定我们要查找遍历的数据范围,即获取最大最小ID记录;
获取最小id的sql如下:
可以看到查询时长达14s,我们查看解析这条sql:
可以看到这条sql走的索引是我们指令类型的索引。
为什么会这样呢?
我们将单个条件拉出来一次查看对应的扫描行数:
created_time>‘2022-06-21’
:扫描495w行
inst_type = ‘2’
:扫描302w行
biz_line in (3,15)
:扫描2095w行:
怎么解决?
解决这个问题有两种方式:
1、改单索引为聚合索引:
ALTER TABLE `cashcow_birch`.`divided_account_inst`
ADD INDEX `dix_type_biz_time`(`inst_type`, `biz_line`, `created_time`);
这样我们在查询时,会命中我们的联合索引,导致我们扫描行数大幅减小
2、缩小查询范围,在不改变原有业务语义的场景下,由于我们现在是获取扫描范围的最小边界,所以可以将时间范围缩小为三个月前的那一天来获取边界值:
select * from divided_account_inst WHERE (created_time > '2022-06-21' and created_time < '2022-06-22' and inst_type = '2' and biz_line in ( 3 , 15 ) and data_source_flag = 0 ) limit 1
我们解析这条sql,发现扫描行数减少到5.6w行
总结
1、在多条件查询时,mysql会优先取扫描行数最少的索引作为该查询的使用索引。
2、在条件查询时,我们的查询条件扫描行数越小,查询时间越少
评论区