目录
一、B树结构索引(B-树)
(1)特点。
(2)问题:范围查询效率??
(3)缺点。
1、查询的不稳定性。
2、各叶子节点无联系。
3、IO资源的消耗较多。
二、B+树结构索引。(标准)
(1)特点。
(2)优点。
1、叶子节点有联系。
2、IO资源的消耗较少。
3、MySQL采用的索引结构。
4、查询稳定性。
(3)为什么说B+Tree比B-Tree更适合实际应用中操作系统的文件索引和数据库索引?
三、MySQL中优化的B+树。
四、索引分类。
(1)MySQL中的主要索引分类。
(2)注意事项。
1、主键索引。
2、唯一索引。
3、常规索引。
4、全文索引。
五、MySQL中InnoDB存储引擎中索引的存储形式。
(1)索引存储形式。
(2)图例演示。
1、聚集索引。(主键索引)
2、二级索引。(其它类型索引)
3、回表查询。
六、关于聚集索引与二级索引的常见面试题。
(1)以下两条SQL语句,哪个执行效率高?为什么?
(2)InnoDB主键索引的B+tree高度一般为多高呢?
1、当B+树的高度为2时。
2、当B+树的高度为3时。
一、B树结构索引(B-树)
(1)特点。
- 注意:对于B树结构的索引,它每个节点(根或子)都存储了数据。
- 也就是在B树中,非叶子节点和叶子节点都会存放数据。
以一个5阶的B树,每一个节点最多存储4个key(值),其中还对应5个指针。
一旦节点存储的key数量到达5,就会裂变,中间元素往上分裂。
- 对上图的B树简单介绍。
对于上面的一颗B树,其中浅蓝色的块称之为一个个磁盘块,每个磁盘块包含几个数据项(白色表示)和指针(黄色表示)。例如磁盘1包含的数据项有17和35,包含的指针p1、p2、p3。
其中p1指向小于17的磁盘块。p2指向大于17,且小于35的磁盘块。而p3指向大于35的磁盘块。
(2)问题:范围查询效率??
- 如果需要进行“范围查询”则效率会降低。如下以一颗最大度数(max-degree)为5(5阶)的b-tree为例,那这个B树每个节点最多存储4个key(值),5 个指针。
- 如果要查询用户的id=4到12之间。它查完4、5、...、9后,又得往回查找10,再往下查找11、12。也就是在B树索引结构时它们的子节点之间并没有相互链接的!
(3)缺点。
1、查询的不稳定性。
- 查找元素的稳定性不高。也就是比较的次数不平衡。
2、各叶子节点无联系。
- 其次就是叶子节点没有相联系,如果进行范围查询,也就是数据落到不同的磁盘块。就要去寻找多次。
3、IO资源的消耗较多。
- 考虑IO流资源。因为我们的数据是存储在表中,而表存储在硬盘当中。而去读数据时,读到内存中,是需要IO读取。而一次性读的越多,IO读取次数越少,也就是消耗的资源少。
- 假设一个磁盘块可以存储16kb大小。但是这个磁盘块又需要存储数据,又要存储指针。数据与指针都占用空间大小。
- 而那个数据又对应一行数据(如id——>行数据——>多列),那么是不是一个磁盘块存储的数据量就减少了?假如存储的数据量达到千万级,是不是IO读取的次数(消耗的IO资源)大大增加!!
二、B+树结构索引。(标准)
(1)特点。
- 对B树结构进行升级(叶子节点之间添加了单向的指针!)这样就很好的支持了范围查询情况。不需要重新走回去。
- B+Tree是B-Tree的变种,现在以一颗最大度数(max-degree)为4(4阶)的b+tree为例,来看一下其结构示意图。
蓝色框框起来的部分,是索引部分。仅仅起到索引数据的作用,不存储数据。
红色框框起来的部分,是数据存储部分。在其叶子节点中要存储具体的数据。
- 所有的数据都存储在叶子节点当中!!
各个叶子节点之间形成一个单向链表。
非叶子节点仅仅起到索引数据作用,具体的数据都是在叶子节点存放的。
(2)优点。
1、叶子节点有联系。
- 各个叶子节点之间通过一个单向链表相联系。
2、IO资源的消耗较少。
- 当所有的数据都存储到叶子节点当中。IO去对应的磁盘块读取数据时,是不是一次读取可以读取到很多数据(因为叶子节点的磁盘块里只存储数据,未存储指针),这样IO的读取次数降低了。
3、MySQL采用的索引结构。
- 这就是为什么MySQL使用的B+树索引结构。B树的缺点就是B+树的优点。
4、查询稳定性。
- 在B+树索引结构当中,最终的数据查询都会落实到叶子节点当中。IO读取次数稳定且相同。
- 无论是根节点、叶子节点数据都会落实到(根——>叶子节点)上。
(3)为什么说B+Tree比B-Tree更适合实际应用中操作系统的文件索引和数据库索引?
- B+Tree的磁盘读写代价更低。
- B+Tree的内部节点并没有指向关键字具体信息的指针。
- 其次它内部节点相对BTree更小,如果把所有同一内部节点的关键字(数据)存放在同一个盘块中,那么盘块所能容纳的关键字数量也越多。一次性读取到内存中的需要查找的关键字(数据)也就越多。相对来说IO读写次数也就降低了
- B+Tree的查询效率更加稳定。
- 由于非叶子节点不是最终指向文件内容的节点,而是叶子节点中关键字(数据)的索引,所以任何关键字的查找都必须走一条从根节点到叶子节点的路。所有查询关键字(数据)的路径长度相同,导致每个数据的查询效率相当。
三、MySQL中优化的B+树。
- 上面所看到的结构是标准的B+Tree的数据结构。
- 接下来,再来看看MySQL中优化之后的B+Tree结构。(将叶子节点变成双向链表联系)
- MySQL的索引数据结构对经典B+Tree进行了优化,在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提供了区间访问的性能。
- 更加有利于排序(支持的是双向链表)。
四、索引分类。
(1)MySQL中的主要索引分类。
- 在MySQL数据库,将B+树的索引结构又具体类型主要分为以下几类:主键索引、唯一索引、常规索引、全文索引。
- 以表格的形式说明。
(2)注意事项。
1、主键索引。
- 当给表中的某个列设置成主键(主键约束)时,MySQL会默认自动创建一个主键索引!
- 如果没有给表中的字段添加索引。MySQL也会给这张表添加一个主键索引——行id。当然加主键时,就会将主键约束加在主键列上
2、唯一索引。
数据要求唯一。且唯一索引可以有多个。
当给表中的某个列设置成唯一约束时,MySQL会默认自动创建一个唯一索引!
3、常规索引。
- 数据不要求唯一,且常规索引可以有多个。
- 可以给任意一个字段添加常规索引。
4、全文索引。
- 用的相对少。
五、MySQL中InnoDB存储引擎中索引的存储形式。
(1)索引存储形式。
- 在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种。
- 聚集索引(也就是主键索引)的叶子节点其实就是存储的是行数据。
- 二级索引就是除了主键索引之外的,都是属于二级索引。
- 二级索引的叶子节点数据存储的不是行数据,而是存储的主键值!
(2)图例演示。
- 以员工表emp为例。其中有员工id(empno)、员工姓名(ename)...等等字段。
1、聚集索引。(主键索引)
- 假设员工表(emp)的字段:员工id(empno)并设置为主健(主键索引)。
- 查询员工id(empno:主键)=7788员工的所有信息。
- 则聚合索引——>叶子节点存储的是对应的行数据!
2、二级索引。(其它类型索引)
- 假设员工表(emp)的字段:员工姓名(ename)并设置唯一健(唯一索引)。
- 查询ename(姓名)="张三"的员工信息。
- 则二级索引——>叶子节点存储的是对应的主键值(主键索引)!
3、回表查询。
- 下面这种先到二级索引中查找数据,找到主键值。然后再到聚集索引中根据主键值,获取数据的方式,就称之为回表查询。
六、关于聚集索引与二级索引的常见面试题。
(1)以下两条SQL语句,哪个执行效率高?为什么?
- 备注: 其中id为主键,name字段创建的有索引。
A. select * from user where id = 10 ; B. select * from user where name = 'Arm' ;
- 回答如下。
- A 语句的执行性能要高于B 语句。
- 因为A语句直接走聚集索引,直接返回数据。
- 而B语句需要先查询name字段的二级索引,然后再查询聚集索引,也就是需要进行回表查询。
(2)InnoDB主键索引的B+tree高度一般为多高呢?
- 假设IO流读取的磁盘块为16kb(也就是一次读一页)。一行数据的大小为1k,一页中可以存储16行这样的数据。
- InnoDB的指针占用6个字节的空间,而主键即使为bigint,其占用字节数为8个字节。
1、当B+树的高度为2时。
- 可以存储:1170*16(每个磁盘对应16k,一行数据1k,则16行)= 18720(条数据)
2、当B+树的高度为3时。
- 可以存储:1170*1170*16 = 21902400(条数据)。2000多万数据了。
- 一般B+树高3~4左右就绝对够用了。