共计 2425 个字符,预计需要花费 7 分钟才能阅读完成。
几个概念
聚簇索引(clustered index)使用 innodb 引擎时,每张表都有一个聚簇索引,比如我们设置的主键就是聚簇索引 特点:查询数据特别快,因为聚簇索引和行数据存储在硬盘的同一页,这样可以减少磁盘 I / O 操作次数(影响 mysql 性能的重要因素)注意:主键索引应该尽量简短
二级索引(secondary index)除了聚簇索引外的其他索引叫做二级索引,比如我们给除主键外其他字段创建的索引 特点:二级索引里面存储了聚簇索引,最后要通过聚簇索引找到行数据。可见,主键索引的效率会影响其他索引
覆盖索引(covering index)索引包含了查询语句需要的所有数据,这种索引称为覆盖索引 特点:索引的叶子节点中已经包含要查询的数据,不需要回表操作所以很快(减少了磁盘 I / O 操作次数)
组合索引(multiple-column index)组合索引也称为复合索引(联合索引),是指把多个字段组合起来创建一个索引(最多 16 个字段)特点:遵循最左前缀匹配原则
最左前缀匹配原则(leftmost prefix principle)mysql 会一直向右匹配直到遇到范围查询 (>、<、between、like) 才停止匹配 举例:我们使用 a,b,c 四个字段创建一个组合索引(a,b,c),那么 where 条件中必须匹配字段 a,mysql 优化器才会用到这个索引 首先匹配字段 a,才能匹配字段 b 首先匹配字段 a,其次匹配字段 b,才能匹配字段 c
准备工作
创建 teacher 表,使用 mobile,name,birthday 字段建立组合索引,注意这三个字段在索引中的顺序
CREATE TABLE `teacher` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`birthday` timestamp NULL DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`mobile` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_one` (`mobile`,`name`,`birthday`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
使用 explain 查看 mysql 执行计划
Type 列:MySQL 在表里找到所需行的方式(由左至右,由最差到最好):| All | index | range | ref | eq_ref | const| system | null |
Extra 列: 额外的信息(由左至右,由差到好):|Using index condition|Using where; Using index|Using index|
使用索引的场景
场景一:mobile 是索引的第一列
explain select * from teacher where mobile = ‘18600660088’;
ref 列只出现了一个 const,说明只用到索引的第一列
场景二:mobile 和 name 是索引中从左到右连续的两列
explain select * from teacher where mobile = ‘18600660088’ and name = ‘kevin chen’;
ref 列出现了两个 const,说明用到索引的第一列和第二列
场景三:mobile、name 和 birthday 是索引中从左到右连续的三列
explain select * from teacher where mobile = ‘18600660088’ and name = ‘kevin chen’ and birthday = ‘2019-01-01’;
ref 列出现了三个 const,说明用到索引的第一列、第二列和第三列
场景四:因为跳过了索引中第二列(name),所以只用到了索引的第一列
explain select age from teacher where mobile = ‘18600660088’ and birthday = ‘2019-01-01’;
ref 列只出现了一个 const,说明只用到索引的第一列
场景五:
explain select * from teacher where mobile = ‘18600660088’ and name like ‘kevin chen’;
场景六:mobile 使用索引
explain select * from teacher where mobile = ‘18600660088’ and name like ‘%kevin chen’;
场景七:mobile 和 name 使用索引
explain select * from teacher where mobile = ‘18600660088’ and name = ‘kevin chen’ and birthday > ‘2019-01-01’;
场景八:mobile 使用索引
explain select * from teacher where mobile like ‘18600660088%’;
不使用索引的场景
场景一:缺少最左边的 mobile 字段
explain select * from teacher where name = ‘kevin chen’;
场景二:缺少最左边的 mobile 字段和第二个 name 字段
explain select * from teacher where birthday = ‘2019-01-01’;
场景三:like 模糊匹配 % 位于最左边
explain select * from teacher where mobile like ‘%18600660088’;
覆盖索引
场景一:使用覆盖索引
explain select mobile,name,birthday from teacher where mobile = ‘18600660088’;
Extra 列表示附加信息,Using index 使用了覆盖索引
场景二:查询的 age 字段不在索引中,不能使用覆盖索引
explain select age from teacher where mobile = ‘18600660088’;