InnoDB插入数据时用的是聚簇(排序)
MyIsam插入数据使用的是堆表(不排序)
如下图所示,其中_前为主键值或索引值, _后的数据为其他列的数据,在每一页中,都有页目录,只存储分组后第一个主键值或索引值
这样可以快速查找
聚簇索引
聚簇索引的特点:
- 按主键值的大小进行记录和页的排序:
数据页(叶子节点)里的记录是按照主键值从小到大排序的一个单向链表。
数据页(叶子节点)之间也是是按照主键值从小到大排序的一个双向链表。
B+树中同一个层的页目录也是按照主键值从小到大排序的一个双向链表。 - B+树的叶子节点存储的是完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。
具有这两种特性的B+树称为聚簇索引,所有完整的用户记录都存放在这个聚簇索引的叶子节点处。这种聚簇索引
并不需要我们在MySQL语句中显式的使用INDEX语句去创建。InnoDB存储引擎会自动的为我们创建聚簇索引(上节讲的row_id在此处可能就发挥了作用)。
在InnoDB存储引擎中,聚簇索引就是数据的存储方式(所有的用户记录都存储在了叶子节点),也就是所谓的索
引即数据,数据即索引。
(存储的大概方式,没话那么细,具体看上面的描述,下面的图红色指针也是双向的。。。没画好,有时间再改 )
一条数据实际应用的时候一般为1K
数据页(叶子节点)为16k,一般为16条记录
非叶子节点中,一般,主键bigInt(8字节)+指针(6byte)=14字节,则非叶子节点可指向16k/14B=1170.28约为1170个数据页
当B+树的深度为2时,可容纳117016=18724条数据
当B+树的深度为3时,可容纳11701170*16=21902400条数据
在实际应用中b+树深度一般最多为3,即最多存2000万条数据,当超过2000万条数据时考虑分表或分布式。
MySQL只把根节点的页保存到内存中,所以当树的深度为2时,进行1次磁盘IO,等输的深度为3时,进行2次磁盘IO
二级索引(赋值索引)
聚簇索引只能在搜索条件是主键值时才能发挥作用,因为B+树中的数据都是按照主键进行排序的。当我们想以别
的列作为搜索条件时我们可以多建几棵B+树,不同的B+树中的数据采用不同的排序规则。
二级索引与聚簇索引有几处不同:
- 按指定的索引列的值来进行排序
- 叶子节点存储的不是完整的用户记录,而只是索引列+主键。
- 目录项记录中不是主键+页号,变成了索引列+页号。
- 在对二级索引进行查找数据时,需要根据主键值去聚簇索引中再查找一遍完整的用户记录,这个过程叫做回表
非叶子节点:
叶子节点(数据页)
联合索引
以多个列的大小为排序规则建立的B+树称为联合索引,本质上也是一个二级索引。
例:index(a,b,c) 也就是说上图的索引值为组合abc,在进行排序时,和字符串的排序类似
目录项纪录的唯一性
当不是主键和唯一索引时,索引值可能相同,于是:
当我们需要保证在B+树的同一层内节点的目录项记录除页号这个字段以外是唯一的。所以对于二级索引的内节点的目录项记录的内容实际上是由三个部分构成的:
1.索引列的值
2.主键值
3.页号
B+树索引总结
- 每个索引都对应一棵B+树。用户记录都存储在B+树的叶子节点,所有目录记录都存储在非叶子节点。
- InnoDB存储引擎会自动为主键(如果没有它会自动帮我们添加)建立聚簇索引,聚簇索引的叶子节点包
含完整的用户记录。 - 可以为指定的列建立二级索引,二级索引的叶子节点包含的用户记录由索引列 + 主键组成,所以如果想
通过二级索引来查找完整的用户记录的话,需要通过回表操作,也就是在通过二级索引找到主键值之后再
到聚簇索引中查找完整的用户记录。 - B+树中每层节点都是按照索引列值从小到大的顺序排序而组成了双向链表,而且每个页内的记录(不论
是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序而形成了一个单链表。如果是联合索引
的话,则页面和记录先按照联合索引前边的列排序,如果该列值相同,再按照联合索引后边的列排序。 - 通过索引查找记录是从B+树的根节点开始,一层一层向下搜索。由于每个页面都按照索引列的值建立了
页目录,所以在这些页面中的查找非常快。