MySQL 的 in 查询到底走不走索引?

首先说一下,我的测试环境:

MySQL 版本:SELECT VERSION(); 

mysql in子查询不走索引 mysql in是否走索引_主键

 

 

 创建测试表zxl_test

CREATE TABLE `zxl_test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(255) NOT NULL,
  `title` varchar(255) DEFAULT NULL,
  `page` bigint(20) DEFAULT NULL,
  `status` tinyint(3) unsigned NOT NULL COMMENT '状态:0 正常,1 冻结,2 删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;

循环插入 100 万条测试数据

DELIMITER ;; 
    CREATE PROCEDURE test_insert()
    BEGIN 
        declare i int;
        set i = 1 ;
        WHILE (i < 1000000) DO
            INSERT INTO zxl_test(`name`,title,`page`,`status`) 
                VALUES(CONCAT('zxl_', i),
                    CONCAT('zxl_title_', i),
                i, (SELECT FLOOR(RAND() * 2)));
            set i = i + 1;
        END WHILE;
        commit; 
END;; 
CALL test_insert();

name列in查询:

mysql in子查询不走索引 mysql in是否走索引_分页查询_02

 

 

status列in查询:

mysql in子查询不走索引 mysql in是否走索引_主键_03

 

 

 可以看到表中的 name 值已经非常的散了,查询时间0.393秒左右,表中的 status in 的情况,耗时 17 秒左右

 

再看一下主键ID in的查询:

mysql in子查询不走索引 mysql in是否走索引_主键_04

 

 

 查询时间耗时 0.009秒左右

 

为了比较,给name列加上索引,in 查询耗时 0.02 秒左右

CREATE INDEX index_zxl_test_name ON zxl_test(`name`(255));

mysql in子查询不走索引 mysql in是否走索引_主键_05

 

 

EXPLAIN 分析发现它们的 type 都是 range,表示使用索引范围查询, 通过索引字段范围获取表中部分数据记录. 这个类型通常出现在 =,<>,>,>=,<,<=,IS NULL,<=>,BETWEEN,IN() 操作中。而且 possible_keys 的值也表明了分别使用主键索引和 index_xttblog_name 索引。并且在 in 索引的情况下,rows 的值,大家都可以看到是 4。以上就可以证明了,在 MySQL 5.7 版本中,in 在有索引的情况下,会走索引进行查询。

 

给status列加上索引,in查询耗时17.483秒

CREATE INDEX index_zxl_test_status ON zxl_test(`status`);

mysql in子查询不走索引 mysql in是否走索引_主键_06

 可以看到有索引和没有索引查询的时间差不多

 

猜想:如果把status字段改为char类型呢?

alter table zxl_test MODIFY COLUMN status CHAR(2) NOT NULL COMMENT '状态:0 正常,1 冻结,2 删除'

mysql in子查询不走索引 mysql in是否走索引_分页查询_07

 

发现并没有提升,接着改为varchar类型的

mysql in子查询不走索引 mysql in是否走索引_MySQL_08

 同样的,查询效率还是差不多

 

试试无索引,分页查询, 发现用时0.059s

mysql in子查询不走索引 mysql in是否走索引_MySQL_09

 

 

试一下有索引,分页查询, 发现用时0.040s,稍微提升了一点

mysql in子查询不走索引 mysql in是否走索引_主键_10

 

 

结论:MySQL 的 in 查询是会走索引的

注意:如果使用in查询,如果结果集中的数据非常多,尽量分页查询处理,不然查询的效率也会低