mysql的in走不走索引?

结论

mysql的in关键字不一定走索引。
个人猜测跟传入的元素个数和索引字段离散程度有关。

验证过程

-- mysql版本
select version(); -- 5.7.28-log

-- 增加索引,该表有1849条记录,38个biz_type
ALTER TABLE `gdata_log_registry` ADD KEY `idx_biz_type` (`biz_type`);

-- 查询执行计划,已脱敏,in里有11个元素
explain SELECT * FROM `gdata_log_registry` WHERE `biz_type` 
IN('A_EXPORT','B_EXPORT','EXCEPTION','CN','L_FUL','FILL','OUT','PC','TI','TIMEOUT','WM')

-- 查询执行计划,已脱敏,in里有9个元素
explain SELECT * FROM `gdata_log_registry` WHERE `biz_type` 
IN('A_EXPORT','B_EXPORT','EXCEPTION','CN','L_FUL','FILL','OUT','PC','TI')

执行计划
执行计划字段解释:

  • id:选择标识符
  • select_type:表示查询的类型。
  • partitions:匹配的分区
  • table:输出结果集的表
  • possible_keys:sql可能使用的索引
  • type:表示表的连接类型
  • key:显示MySQL实际使用的索引。如果没有选择索引,键是NULL
  • key_len:索引字段的长度
  • ref:列与索引的比较
  • rows: 显示执行查询时扫描的行数。(估算的行数)
  • filtered:按表条件过滤的行百分比
  • extra:描述,当出现Using filesor或Using temproary时,表示无法用索引,需要考虑做优化。

其他

type结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

  • all:全表扫描
  • index:另一种形式的全表扫描,只不过他的扫描方式是按照索引的顺序
  • range:有范围的索引扫描,相对于index的全表扫描,他有范围限制,因此要优于index
  • ref: 查找条件列使用了索引而且不为主键和unique。其实,意思就是虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。
  • const:通常情况下,如果将一个主键放置到where后面作为条件查询,mysql优化器就能把这次查询优化转化为一个常量。至于如何转化以及何时转化,这个取决于优化器

一般来说,要保证查询达到range级别,最好能达到ref,type出现index和all时,表示走的是全表扫描没有走索引,当全表数据太多时效率低下,这时需要进行sql调优。

参考:

https://www.cnblogs.com/tufujie/p/9413852.html
https://blog.csdn.net/yexiaomodemo/article/details/108713770

猜你喜欢

转载自blog.csdn.net/zimou5581/article/details/112428352