B+树
17-
B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。
innodb中页的 默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更 大,树就会更矮更胖,
如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。
B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。
那么B+树使得范围查找, 排序查找,分组查找以及去重查找变得异常简单。
31-b+
B+ 树是以 N 叉树的形式存在的,这样有效降低了树的高度,
查找数据也不需要全表扫描了,顺着根节点层层往下查找能 很快地找到我们的目标数据,
每个节点的大小即一个磁盘块(页)的大小,一次 IO 会将一个磁盘块的数据都读入
(即磁 盘预读,程序局部性原理:读到了某个值,很大可能这个值周围的数据也会被用到,干脆一起读入内存),
叶子节点通过 指针的相互指向连接,能有效减少顺序遍历时的随机 IO,而且我们也可以看到,叶子节点都是按索引的顺序排序好的,
这也意味着根据索引查找或排序都是排序好了的,不会再在内存中形成临时表
32-
- 仍然是N叉树,层级小,非叶子节点不再存储数据,数据只存储在同一层的叶子节点上,B+树从根到每一个节点 的路径长度一样,而B树不是这样
- 叶子之间,增加了链表(图中红色箭头指向),获取所有节点,不再需要中序遍历,使用链表的next节点就可以快 速访问到
- 范围查找方面,当定位min与max之后,中间叶子节点,就是结果集,不用中序回溯(范围查询在SQL中用得很 多,这是B+树比B树最大的优势)
- 叶子节点存储实际记录行,记录行相对比较紧密的存储,适合大数据量磁盘存储;非叶子节点存储记录的PK,用 于查询加速,适合内存存储
- 非叶子节点,不存储实际记录,而只存储记录的KEY的话,那么在相同内存的情况下,B+树能够存储更多索引
-存储越规律,查找性能越牛逼
让书籍,按照「字典排序」升序存储,于是我们可以进行「二分查找」,
时间复杂度从 O(n) -> O(log2n),缺点是每次插入都要排序;
让书籍,按照「Hash 表」的结构进行存储,于是我们可以进行「Hash 查找」,
用空间换时间,时间复杂度 O(1);
让书籍,按照「二叉树」的结果进行存储,
于是我们可以进行「二叉查找」,时间复杂度 O(log2n);
二叉树极端情况下会退化成 O(n),于是有了「平衡二叉树」;
平衡二叉树终究还是“二叉”,只有两个子节点,一次从磁盘 load 的数据太少,
于是有了可以有多于 2 个子节点的 B 树;
B 树找出来的数据,是无序的,如果你要求数据排好序返回,还要在内存手动排一次序,
于是有了叶子节点是一个双向链表的 B+ 树;
你再也不能随意插入数据,因为你要维护数据的规律性,
不管你是顺序存储还是 B+ 树,都要找到正确的位置进行插入;
所以为了查找方便,写的时候就得牺牲。
-如何选择自己数据库?
如果你需要数据安全可靠,最好是用 Mysql 这样的关系型数据库;
如果你只是缓存一些临时数据,需要快速查询,不妨用 Redis 这样的 Key-Value 内存数据库;
如果你想放一些文档,并且还可以支持「相关性搜索」,那像 Elasticsearch 这样的搜索引擎,则是你的首选。
78-
数据记录本身被存于主索引(一颗B+Tree)的叶子节点上,
这就要求同一个叶子节点内(大小为一个内存页或磁盘 页)的各条数据记录按主键顺序存放
因此每当有一条新的记录插入时,
MySQL会根据其主键将其插入适当的节点和位置,
如果页面达到装载因子(InnoDB默认为 15/16),
则开辟一个新的页(节点)
79-主键为什么要连续自增
如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动 开辟一个新的页
如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有 索引页得中间某个位置
82-uuid
UUID的字符串存储,查询效率慢
BLOB是一个二进制对象,可以容纳可变数量的数据。有四种类型的BLOB:TINYBLOB、BLOB、
MEDIUMBLO和 LONGBLOB TEXT是一个不区分大小写的BLOB。四种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT 和
LONGTEXT。
BLOB 保存二进制数据,TEXT 保存字符数据。
115-
系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取
出来,而不是需要什么取什么。
InnoDB 存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。InnoDB 存储引擎中默认每个页的大小 为16KB,可通过参数
innodb_page_size
将页的大小设置为 4K、8K、16K,在 MySQL 中可通过如下命令查看页的大小:
show variables like 'innodb_page_size';
而系统一个磁盘块的存储空间往往没有这么大,
因此 InnoDB 每次申请磁盘空间时都会是若干地址连续磁盘块来 达到页的大小 16KB。
InnoDB 在把磁盘数据读入到磁盘时会以页为基本单位,
在查询数据时如果一个页中的每 条数据都能有助于定位数据记录的位置,
这将会减少磁盘I/O次数,提高查询效率。
116-
那为什么推荐使用整型自增主键而不是选择UUID? UUID是字符串,比整型消耗更多的存储空间;
在B+树中进行查找时需要跟经过的节点值比较大小,整型数据的比较运算比字符串更快速;
自增的整型索引在磁盘中会连续存储,在读取一页数据时也是连续;UUID是随机产生的,读取的上下两行数
据存储是分散的,不适合执行where id > 5 && id < 20的条件查询语句。
在插入或删除数据时,整型自增主键会在叶子结点的末尾建立新的叶子节点,不会破坏左侧子树的结构;
UUID主键很容易出现这样的情况,B+树为了维持自身的特性,有可能会进行结构的重构,消耗更多的时间。