MySQL为什么使用B+树来作索引
5 分钟阅读
•
843 字
+
395 词
参考答案
- 单点查询 :B 树进行单个索引查询时,最快可以在 O(1) 的时间代价内就查到。从平均时间代价来看,会比 B+ 树稍快一些。但是 B 树的查询波动会比较大 ,因为 每个节点既存索引又存记录 ,所以有时候访问到了非叶子节点就可以找到索引,而 有时需要访问到叶子节点才能找到索引 。 B+树的非叶子节点不存放实际的记录数据 , 仅存放索引 ,所以 数据量相同的情况下 ,相比存储即存索引又存记录的 B 树, B+树的非叶子节点可以存放更多的索引 ,因此 B+ 树可以比 B 树更「矮胖」, 查询底层节点的磁盘 I/O次数会更少 。
- 插入和删除效率 :**B+ 树有大量的冗余节点,删除一个节点的时候,可以直接从叶子节点中删除,甚至可以不动非叶子节点,删除非常快。**B+ 树的插入也是一样,有冗余节点,插入可能存在节点的分裂(如果节点饱和),但是最多只涉及树的一条路径。B 树没有冗余节点,删除节点的时候非常复杂,可能涉及复杂的树的变形。
- 范围查询 : B+ 树所有叶子节点间有一个链表进行连接 ,而 B 树没有将所有叶子节点用链表串联起来的结构,因此只能通过 树的遍历 来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,**范围查询效率不如 B+ 树。**存在大量范围检索的场景,适合使用 B+树,比如数据库。而对于大量的单个索引查询的场景,可以考虑 B 树,比如nosql的MongoDB。
以下是 MySQL 选择 B+ 树而非跳表的深层原因:
- B+树更适合磁盘IO B+Tree一个节点是一个page,是一种多叉树结构,每个结点都是一个16k的数据页,能存放较多索引信息。一次IO一个page,大大节省了磁盘IO的操作。 B+Tree一个page 能存放较多索引信息 ,所以树的层数比较低, 三层左右就可以存储2kw左右的数据也就是说查询一次数据,如果这些数据页都在磁盘里,那么最多需要查询三次磁盘IO。 原生跳表不适合磁盘IO 跳表是链表结构,一条数据一个结点,那么一个node节点一次磁盘io, 一个page 页规模的IO存储的性能 估计要下降1000倍以上。 原生跳表 一个node存放一个 索引信息 , 所以树的层数比较高 如果最底层要存放2kw数据,且每次查询都要能达到二分查找的效果,2kw大概在2的24次方 左右, 所以,2kw数据的跳表大概高度在24层左右。 如果要进行查找,大概要进行 24次磁盘IO。 这里讲的是原生跳表, 如果经过各种改进,那个不在此文讨论范围。 所以,虽然在理论上,跳表的时间复杂度和B+树相同 ,但是: B+树更适合 磁盘IO, 更合适MYSQL。 从反面来说, 跳表更适合内存IO, 更适合redis。 那么,为啥 redis 用跳表而不用B+树?