B+ 树索引

B+ 树索引 #

没有索引的查找 #

没有索引的时候是怎么查找记录的?比如:

SELECT [列名列表] FROM 表名 WHERE 列名 = xxx;

在一个页中的查找 #

如果表中的记录比较少,所有的记录都可以被存放到一个页中,在查找记录的时候可以根据搜索条件的不同分为两种情况:

  • 以主键为搜索条件 在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录。

  • 以其他列作为搜索条件 对非主键列,数据页中并没有对非主键列建立所谓的页目录,所以无法通过二分法快速定位相应的槽。这种情况下只能从最小记录开始 依次遍历单链表中的每条记录,然后对比每条记录是不是符合搜索条件。很显然,这种查找的效率是非常低的。

在很多页中查找 #

大部分情况下表中存放的记录都是非常多的,需要好多的数据页来存储这些记录。在很多页中查找记录的话可以分为两个步骤:

  1. 定位到记录所在的页。
  2. 从所在的页内中查找相应的记录。

由于并不能快速的定位到记录所在的页,所以只能从第一个页沿着双向链表一直往下找,每一个页中再使用上面一个页中的查找方法。非常 低效。

索引 #

先建一个表:

mysql> CREATE TABLE index_demo(
    ->     c1 INT,
    ->     c2 INT,
    ->     c3 CHAR(1),
    ->     PRIMARY KEY(c1)
    -> ) ROW_FORMAT = Compact;
Query OK, 0 rows affected (0.03 sec)

简单的索引方案 #

根据某个搜索条件查找一些记录时为什么要遍历所有的数据页?

因为各个页中的记录并没有规律,我们并不知道搜索条件匹配哪些页中的记录,所以不得不依次遍历所有的数据页。

那么,如何快速定位记录所在的数据页?

也可以建一个目录:

B+ 树 #

聚簇索引 #

  1. 使用记录主键值的大小进行记录和页的排序
  2. B+ 树的叶子节点存储完整的用户记录(记录中存储了所有列的值,包括隐藏列)。

具有这两种特性的 B+ 树称为聚簇索引,所有完整的用户记录都存放在这个聚簇索引的叶子节点处。这就是所谓的索引即数据,数 据即索引

二级索引 #

联合索引 #

B+ 树索引的注意事项 #

索引的使用 #