CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NULL DEFAULT NULL,
`b` int(11) NULL DEFAULT NULL,
`c` int(11) NULL DEFAULT NULL,
`d` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `index_abc`(`a`, `b`, `c`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `t1` VALUES (1, 13, 12, 4, 'dll');
INSERT INTO `t1` VALUES (2, 1, 5, 4, 'doc');
INSERT INTO `t1` VALUES (3, 13, 16, 5, 'img');
INSERT INTO `t1` VALUES (4, 12, 14, 3, 'xml');
INSERT INTO `t1` VALUES (5, 1, 1, 4, 'txt');
INSERT INTO `t1` VALUES (6, 13, 16, 1, 'exe');
INSERT INTO `t1` VALUES (7, 5, 3, 6, 'pdf');
建立 a、b、c
三列的联合索引 index_abc
,数据表数据如下图
select * from table_name where a = '1' and b = '2' and c = '3'
select * from table_name where b = '2' and a = '1' and c = '3'
select * from table_name where c = '3' and b = '2' and a = '1'
......
3
条 SQL
语句都用到了联合索引。where
子句几个搜索条件顺序调换不影响查询结果,因为 MySQL
中有查询优化器,会自动优化查询顺序*
select * from table_name where a = '1'
select * from table_name where a = '1' and b = '2'
select * from table_name where a = '1' and b = '2' and c = '3'
都从最左边开始连续匹配,3
条 SQL
语句都用到了联合索引
select * from table_name where b = '2'
select * from table_name where c = '3'
select * from table_name where b = '1' and c = '3'
这些没有从最左边开始,最后查询没有用到索引,都用的是全表扫描
select * from table_name where a = '1' and c = '3'
如果查询字段不连续时, 虽然 a
和 c
列可以匹配,但 b
列无法匹配,所以没没有使用到联合索引
如果列是字符型的话它的比较规则是先比较字符串的第一个字符,第一个字符小的哪个字符串就比较小,如果两个字符串第一个字符相同,那就再比较第二个字符,第二个字符比较小的那个字符串就比较小,依次类推,比较字符串
如果 a
是字符类型,那么前缀匹配用的是索引,后缀和中缀只能全表扫描了
select * from table_name where a like 'As%'; // 前缀都是排好序的,走索引查询
select * from table_name where a like '%As'; // 全表查询
select * from table_name where a like '%As%'; // 全表查询
SELECT * FROM t1 WHERE a > 1
EXPLAIN
执行计划说明 没有使用到联合索引,是全表扫描>、<、between、like
就会停止匹配SELECT * FROM t1 WHERE a > 1 AND a < 12
可以对最左边的列进行范围查询,可以用到联合索引。EXPLAIN
执行计划如下图
执行计划中的 type
字段是 range
,它指的是:它是索引上的范围查询,它会在索引上扫描特定范围内的值
SELECT * FROM t1 WHERE a > 1 AND a < 12 AND b > 1
虽然在 1 < a < 12
的范围内 b
是无序的,但 b
字段由于是范围查询,所以找到 1< a < 12
的记录后,可以根据条件 b > 1
继续范围过滤查找,是可以用到联合索引的
SELECT * FROM t1 WHERE a > 1 AND b > 3 AND c > 2
第一、二、三列同时范围查询, 没有使用到联合索引,是全表扫描
如果左边的列是精确查找的,右边的列可以进行范围查找
SELECT * FROM t1 WHERE a = 1 AND b > 3;
a = 1
的情况下 b
是有序的,进行范围查找走的是联合索引
SELECT * FROM t1 WHERE a = 1 AND b > 3 AND c = 4
虽然 b > 3
是范围查询,但 EXPLAIN
执行计划说明依然使用的是联合索引
SELECT * FROM t1 WHERE a = 1 AND b > 3 AND c > 2
虽然 b > 3
和 c > 2
是范围查询,但 EXPLAIN
执行计划说明依然使用的是联合索引
SELECT * FROM t1 WHERE a = 1 AND b =5 AND c > 2
EXPLAIN
执行计划说明依然 使用的是联合索引