MySQL 之 非聚簇索引 和 聚簇索引
概要
聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,MyISAM 通过 key_buffer 把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在 key buffer 命中时,速度慢的原因
聚簇索引
InnDB 使用的是聚簇索引。其数据文件本身就是索引文件,也就是主索引,其 B+ 树叶结点的 key 存储的就是主键,data域存储的就是完整的数据记录,而非指向地址。而其他索引都被作为辅助索引,辅助索引 B+ 树的 key 存储的就是 辅助键,data 域存储的却是主键的值。所以当根据辅助索引查询数据时,我们会得到的主键值,然后再走一遍主索引,最后得到完整的数据记录。
非聚簇索引
MyISAM 使用的是非聚簇索引,主键索引 B+树 叶结点的 key 存储的就是主键,辅助键索引 B+树 叶结点的 key 存储的就是辅助键(除了主键,其他都是辅助键)。但其B+ 树叶结点的 data 域存储的是指向数据记录的地址(指针),而非数据本身。 所以各自的索引 B+ 树都是独立的。
PS: 非聚集索引的叶子节点并不一定存放数据的指针, 因为二级索引的叶子节点就存放的是主键,根据主键再回表查数据。
聚簇索引的优点与缺点
优点:查询的快
缺点:1. 依赖于有序的数据。2. 更新代价大
非聚簇索引的优点与缺点
优点:更新代价比聚集索引要小
缺点:1. 也依赖于有序的数据。2. 可能会二次查询(回表)
适用情况(百度百科)
1、含有大量非重复值的列。
2、使用BETWEEN,>,>=,<或<=返回一个范围值的列
3、被连续访问的列
4、返回大型结果集的查询
5、经常被使用连接或GROUP BY子句的查询访问的列
下面的表总结了何时使用聚集索引或非聚集索引:
动作描述 | 使用聚集索引 | 使用非聚集索引 |
---|---|---|
列经常被分组排序 | 应 | 应 |
返回某范围内的数据 | 应 | 不应 |
一个或极少不同值 | 不应 | 不应 |
小数目的不同值 | 应 | 不应 |
大数目的不同值 | 不应 | 应 |
频繁更新的列 | 不应 | 应 |
外键列 | 应 | 应 |
主键列 | 应 | 应 |
频繁修改索引列 | 不应 | 应 |
MySQL 中聚簇索引的设定
聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键来作为聚簇索引。InnoDB 只聚集在同一个页面中的记录。包含相邻健值的页面可能相距甚远。