关于InnoDB索引及相关知识的个人理解,如遇错误欢迎指正。
InnoDB的索引分为两类:
聚集索引(clustered index) 聚集索引的叶子节点存储行记录 一个InnoDB引擎的表,必须有且只有一个聚集索引 聚集索引的三种情况: 如果表定义了PK(primary key),则PK就是聚集索引; 如果表没有定义PK,则第一个not NULL unique列是聚集索引; 否则,InnoDB会创建一个隐藏的row-id作为聚集索引; 普通索引(secondary index) 一个InnoDB引擎的表,可以有任意个普通索引 普通索引的叶子节点存储主键值(MyISAM的索引叶子节点存储记录指针,不要混淆) 普通索引也包含常见的索引种类: 唯一索引(Unique Indexes) 列索引(Column indexes,就是普通的INDEX) 联合/复合索引(Composite indexes,就是多字段的INDEX) 全文索引(FULLTEXT Indexes,MySQL5.6开始,InnoDB也有全文索引了) 空间索引(Spatial Indexes)假设有表:
table name (
id PRIMARY KEY,
name KEY,
sex,
flag
);
其中:id是聚集索引,name是普通索引。
回表是什么回表这个名词其实没有直接的英文翻译,我仅在《高性能MySQL》英文原版中找到几句相关的描述(大概都在第五章后半段):
“look up full rows from the table to retrieve columns”
" it will have to look up each row it finds in the index"
所以其实很简单,回表,就是表达当WHERE索引列的时候,无法直接获取到查询的列,从而导致我们需要再次回到表中去查询相应的内容,就是我们平常所说的“回表”
见下图
两个B+树索引分别如上图:
由此可见,普通索引的查询过程,需要扫码两遍索引树,这个行为也称之为回表
这里面做一个细化的区分:
以下截图来自于MySQL术语表
覆盖索引
覆盖索引是一次查询(query)便取回全部列的索引。它替代了使用索引值作为指针来查找全部表行,这种查询返回的值来自于索引结构,节省硬盘I/O。相比MyISAM,InnoDB可以将这项优化技术应用在更多的列上,因为InnoDB的普通索引还包括主键列。不过InnoDB不能应用这项技术于由事务修改的表的查询,直到事务结束
在正确的查询条件下,任何列索引(column index)或复合索引(composite index)都可以作为覆盖索引。尽可能设计索引和查询以利用这种优化技术。
上面引文有一句话让人耳目一新,就是“InnoDB secondary indexes also include the primary key columns”,InnoDB普通索引包含主键列?之前不是说主键列一般都是聚集索引吗?
这是一个语义误区,实际上MySQL官方文档对于Secondary indexes的定义是,除聚集索引以外的所有索引都称为辅助索引(或叫普通索引),见下图:
总结:也就是说,聚集索引通常为主键,但是普通索引除了包含自己的列以外,还会包含主键列的值,聚集索引在InnoDB引擎的表结构中必须要有,但是普通索引可能有任意个(0个,1个,甚至更多)
此索引类型非彼索引类型,所以有时候加上英文来区分定义是个很好的选择
以下是MySQL官网对于每种存储引擎所支持的索引类型:
(注意:这里看到MyISAM不支持HASH类型)
这里不翻译了,总结几个要点:
什么是最左匹配原则?
根据业务需求,where子句中使用最频繁的一列放在最左边,因为MySQL索引查询会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。所以当我们创建一个联合索引的时候,如(key1,key2,key3),相当于创建了(key1)、(key1,key2)和(key1,key2,key3)三个索引,这就是最左匹配原则。