playMySQL

B+樹

從頁到索引

圖格式 因为这些16KB的页在物理存储上可能并不挨着,所以如果想从这么多页中根据主键值快速定位某些记录所在的页,我们需要给它们做个目录,每个页对应一个目录项,每个目录项包括下边两个部分:

如果一頁不夠存儲索引的,那麼新增頁存儲罷了 现在以查找主键为20的记录为例,根据某个主键值去查找记录的步骤就可以大致拆分成下边两步:

我们现在的存储目录项记录的页有两个,即页30和页32,又因为页30表示的目录项的主键值的范围是[1, 320) ,页32表示的目录项的主键值不小于320,所以主键值为20的记录对应的目录项记录在页30中。

如果索引數據太多,檢索效率下降,那麼可以給索引之上再建立索引,由此產生了二層索引、三層索引⋯⋯ 我们的实际用户记录其实都存放在B+树的最底层的节点上,这些节点也被称为叶子节点或叶节点, 其余用来存放目录项的节点称为非叶子节点或者内节点,其中B+树最上边的那个节点也称为根节点。

聚簇索引

在InnoDB存储引擎中,聚簇索引就是数据的存储方式(所有的用户记录都存储在了叶子节点),也就是所谓的索引即数据,数据即索引。

二級索引

使用非主鍵的其他一個字段建立的索引,稱為二級索引。二級索引的葉子節點只存儲索引列和主鍵值,查詢需要回到聚簇索引中回表。

聯合索引

使用非主鍵的其他多個字段建立的索引,稱為聯合索引。聯合索引的葉子節點存儲索引列1,索引列2和主鍵值,排序以索引列1值為主排序,當索引列1值都一樣的時候以索引列2值排序。

InnoDB的B+树索引的注意事项

根页面万年不动窝

B+树的形成过程是这样的:

内节点中目录项记录的唯一性

为了让新插入记录能找到自己在那个页里,我们需要保证在B+树的同一层内节点的目录项记录除页号这个字段以外是唯一的。所以对于二级索引的内节点的目录项记录的内容实际上是由三个部分构成的:

如下表 |c1| c2| c3| |—-|—-|—-| |1 |1| ‘u’| |3 |1| ‘d’| |5 |1| ‘y’| |7 |1| ‘a’|

把主键值也添加到二级索引内节点中的目录项记录了,这样就能保证B+树每一层节点中各条目录项记录除页号这个字段外是唯一的, 所以我们为c2列建立二级索引后的示意图实际上应该是这样子的: 插入记录(9, 1, ‘c’)时,可以知道應該插在頁5中

一个页面最少存储2条记录