https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
时间复杂度:O(N)
时间复杂度:O(logn)
如果数据插入是递增或者递减顺序的话,会使树成为链式结构。 时间复杂度:O(N)
为了保证平衡,在插入或者删除的时候必须要旋转,通过插入或者删除性能的损失来弥补查询性能的提升。
但如果写请求和读请求一样多的时候怎么办?
随着数据的插入,树的深度会变深,树的深度越深,意味着 IO 次数越多。影响数据读取的效率。
MySQL 的页大小是16k。假设只有data 占用空间且占用 1k 一个磁盘块可以放置16条记录,三层就是 4096条记录。肯定小于 4096.
如果想要放入更多的数据的化,得加层。加层 IO 量肯定上来了。
data 太占内存,导致存储数据太少。
MySQL加载索引是以磁盘块(页)为单位的,页(Page)是 Innodb 存储引擎用于管理数据的最小磁盘单位。默认的页大小为 16KB。
假设只有 p1+key 值 占用空间且占用 10字节, 一个磁盘块可以放置1600条记录,三层就是 40960000条记录。
在B+树 上有两个头节点,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有的叶子节点(即数据节点)之间是一种链式环结构,因此可以对 B+树 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。
让当前key值尽可能的少占用存储空间,才能保证存储更多的值。降低树的高度,减少IO。
保证key的长度越小越好。
谈到索引,大家并不陌生。索引本身是一种数据结构,存在的目的主要是为了缩短数据检索的时间,最大程度减少磁盘 IO。
任何有数据的场景几乎都有索引,比如手机通讯录、文件系统(ext4\xfs\ntfs)、数据库系统(MySQL\Oracle)。数据库系统和文件系统一般都采用 B+ 树来存储索引信息,B+ 树兼顾写和读的性能,最极端时检索复杂度为 O(logN),其中 N 指的是节点数量,logN 表示对磁盘 IO 扫描的总次数。
MySQL 支持的索引结构有四种:B+ 树,R 树,HASH,FULLTEXT。
B 树是一种多叉的 AVL 树。B-Tree 减少了 AVL 数的高度,增加了每个节点的 KEY 数量。
B 树的特性:(m 为阶数:结点的孩子个数最大值)
1. 树中每个节点最多含有 m 个孩子节点 (m>=2);
2. 除根节点和叶子结点外,其他节点的孩子数量 >=ceil(m / 2);
3. 若根节点不是叶子结点,最少有两个孩子
特殊情况:没有孩子的根结点,即根结点为叶子结点,整棵树只有一个根节点;
4. 每个非叶子结点中包含有 n 个关键字信息:(n,P0,K1,P1,K2,P2,......,Kn,Pn) 其中:
Ki (i=1...n) 为关键字,且关键字按顺序升序排序 K(i-1)<Ki
Pi 为指向儿子节点的指针,且指针 P(i-1) 指向的儿子节点里所有关键字均小于 Ki,但都大于 K(i-1)
关键字的个数 n 必须满足:[ceil(m / 2)-1]<= n <= m-1
如果一个结点有 n 个关键字,那么该结点有 n+1 个分支。这 n+1 个关键字按照递增顺序排列
所有叶子结点都出现在同一层,是所有遍历的终点位置
事实上,在MySQL数据库中,诸多存储引擎使用的是B+树,即便其名字看上去是BTREE。
4.1 innodb的索引机制
先以innodb存储引擎为例,说明innodb引擎是如何利用B+树建立索引的
首先创建一张表:zodiac,并插入一些数据
对于innodb来说,只有一个数据文件,这个数据文件本身就是用B+树形式组织,B+树每个节点的关键字就是表的主键,因此innode的数据文件本身就是主索引文件,如下图所示,主索引中的叶子页(leaf page)包含了数据记录,但非叶子节点只包含了主键,术语“聚簇”表示数据行和相邻的键值紧凑地存储在一起,因此这种索引被称为聚簇索引,或聚集索引。
这种索引方式,可以提高数据访问的速度,因为索引和数据是保存在同一棵B树之中,从聚簇索引中获取数据通常比在非聚簇索引中要来得快。
所以可以说,innodb的数据文件是依靠主键组织起来的,这也就是为什么innodb引擎下创建的表,必须指定主键的原因,如果没有显式指定主键,innodb引擎仍然会对该表隐式地定义一个主键作为聚簇索引。
同样innodb的辅助索引,如下图所示,假设这些字符是按照生肖的顺序排列的(其实我也不知道具体怎么实现,不要在意这些细节,就是举个例子),其叶子节点中也包含了记录的主键,因此innodb引擎在查询辅助索引的时候会查询两次,首先通过辅助索引得到主键值,然后再查询主索引,略微有点啰嗦
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)