对MySQL复合索引结合具体示例,各条件下索引使用情况的运行结果及分析。
目录
复合索引示例
假设某个表有一个联合索引(c1,c2,c3,c4)。
A where c1 = ? and c2 = ? and c4 > ? and c3 = ?
B where c1 = ? and c2 = ? and c4 = ? order by c3
C where c1 = ? and c4 = ? group by c3, c2
D where c1 = ? and c5 = ? order by c2, c3
E where c1 = ? and c2 = ? and c5=? order by c2, c3
有谁知道下面A-E能否可以使用索引!!为什么?
创建表
创建一个表,表引擎为MYISAM,并设置包含四个列的复合索引。
SQL语句如下:
sql
CREATE TABLE `fuhe` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`c1` char(1) DEFAULT '',
`c2` char(1) DEFAULT '',
`c3` char(1) DEFAULT '',
`c4` char(1) DEFAULT '',
`c5` char(1) DEFAULT '',
PRIMARY KEY (`id`),
KEY `c1` (`c1`,`c2`,`c3`,`c4`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
新增数据
在上述表中新增部分数据,语句如下:
sql
INSERT INTO `test`.`fuhe` (`id`, `c1`, `c2`, `c3`, `c4`, `c5`) VALUES ('1', 'a', 'b', 'c', 'd', 'e');
INSERT INTO `test`.`fuhe` (`id`, `c1`, `c2`, `c3`, `c4`, `c5`) VALUES ('2', 'A', 'b', 'c', 'd', 'e');
INSERT INTO `test`.`fuhe` (`id`, `c1`, `c2`, `c3`, `c4`, `c5`) VALUES ('3', 'a', 'B', 'c', 'd', 'e');
查询数据
选项A
SQL查询
where c1 = ? and c2 = ? and c4 > ? and c3 = ?
sql
# where c1 = ? and c2 = ? and c4 > ? and c3 = ?
SELECT * FROM `fuhe` where c1 = 'a' and c2 = 'b' and c4 > 'a' and c3 = 'c';
运行结果:

explain分析
sql
explain SELECT * FROM `fuhe` where c1 = 'a' and c2 = 'b' and c4 > 'a' and c3 = 'c';
运行结果:

说明:
通过key_len属性12可知,utf8每个索引长度为3,使用了4列的索引;故复合索引的c1 c2 c3 c4列索引都使用上了。因为c4是范围查找,所以type类型为range。
选项B
SQL查询
where c1 = ? and c2 = ? and c4 = ? order by c3
sql
# where c1 = ? and c2 = ? and c4 = ? order by c3
SELECT * FROM `fuhe` where c1 = 'a' and c2 = 'b' and c4 = 'd' order by c3;
运行结果:

explain分析
sql
explain SELECT * FROM `fuhe` where c1 = 'a' and c2 = 'b' and c4 = 'd' order by c3;
运行结果:

说明:
使用了复合索引的c1 c2列,c3列只是参与了排序。如果c3列没有索引就会进行文件排序。
选项C
SQL查询
where c1 = ? and c4 = ? group by c3, c2
sql
# where c1 = ? and c4 = ? group by c3, c2
SELECT * FROM `fuhe` where c1 = 'a' and c4 = 'd' group by c3, c2;
运行结果:

explain分析
sql
explain SELECT * FROM `fuhe` where c1 = 'a' and c4 = 'd' group by c3, c2;
运行结果:

说明:
只使用了复合索引的c1列,而且由于group by并不是按照索引顺序进行分组的,导致使用了临时表和文件排序。
选项D
SQL查询
where c1 = ? and c5 = ? order by c2, c3
sql
# where c1 = ? and c5 = ? order by c2, c3
SELECT * FROM `fuhe` where c1 = 'a' and c5 = 'e' order by c2, c3;
运行结果:

explain分析
sql
explain SELECT * FROM `fuhe` where c1 = 'a' and c5 = 'e' order by c2, c3;
运行结果:

说明:
通过索引长度判断,只使用到了复合索引的第一列c1,c2 c3列参与了排序,因为c5列未创建索引故using where。
选项E
SQL查询
where c1 = ? and c2 = ? and c5=? order by c2, c3
sql
# where c1 = ? and c2 = ? and c5=? order by c2, c3
SELECT * FROM `fuhe` where c1 = 'a' and c2 = 'b' and c5 = 'e' order by c2, c3;
运行结果:

explain分析
sql
explain SELECT * FROM `fuhe` where c1 = 'a' and c2 = 'b' and c5 = 'e' order by c2, c3;
运行结果:

说明:
使用了复合索引的前两列,因为是按照索引顺序进行排序的,c2 c3列参与了排序,最后的c5没有创建索引,故使用了where条件,其他都是在索引树上扫描的。
总结
对MySQL复合索引结合具体示例,各条件下索引使用情况的运行结果及分析。