B+Tree
索引片:
索引片就是 SQL 查询语句在执行中需要扫描的一个索引片段,我们会根据索引片中包含的匹配列的数量不同,将索引分成窄索引(比如包含索引列数为 1 或 2)和宽索引(包含的索引列数大于 2),宽索引设计合理能有效减少回表查询,但过度的设计会造成索引空间的过大以及新增数据对于索引维护的耗时。
过滤因子:
描述了谓词的选择性。在 WHERE 条件语句中,每个条件都称为一个谓词,谓词的选择性也等于满足这个条件列的记录数除以总记录数的比例。
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_name` varchar(255) DEFAULT NULL COMMENT '用户name',
`user_code` varchar(255) DEFAULT NULL COMMENT '用户code',
`user_age` integer(3) DEFAULT NULL COMMENT '用户age',
PRIMARY KEY (`id`)
) ENGINE=InnoDB
where 条件后面的谓语条件在name数据过滤的数据达到1%,age数据过滤的数据达到54%,那么where user_age = ‘’ and user_name = ‘’ 的过滤因子是优于where user_name = ‘’ and user_age = ‘’。
三星索引:
1、在 WHERE 条件语句中,找到所有等值谓词中的条件列,将它们作为索引片中的开始列;
2、将 GROUP BY 和 ORDER BY 中的列加入到索引中;
3、将 SELECT 字段中剩余的列加入到索引片中。
为了保障数据的不丢失,索引是存在硬盘中的,每次查询都需要与硬盘进行交互,因此合理的索引结构就是要做到更少的与磁盘进行IO次数。
二叉树和平衡二叉树
当二叉树的左右树的深度差太多的时候,二叉树可能直接退化成链表的结构,针对于此人们提出了平衡二叉搜索树(AVL 树),它在二分搜索树的基础上增加了约束,每个节点的左子树和右子树的高度差不能超过 1,也就是说节点的左子树和右子树仍然为平衡二叉树。即使改进后的平衡二叉树的深度也是很多,影响查询效率,这也就引出了B树。
B树
B+树
B+ 树基于 B 树做出了改进,主流的 DBMS 都支持 B+ 树的索引方式
B+ 树和 B 树的差异在于以下几点:
1、有 k 个孩子的节点就有 k 个关键字。也就是孩子数量 = 关键字数,而 B 树中,孩子数量 = 关键字数 +1。
2、B+树非叶子节点的关键字也会同时存在在子节点中,并且是在子节点中所有关键字的最大(或最小),所以B树的数据可能会在非叶子节点上,而B+树的数据只在叶子节点上。。
3、B+树非叶子节点仅用于索引,不保存数据记录,跟记录有关的信息都放在叶子节点中。而 B 树中,非叶子节点既保存索引,也保存数据记录。
4、B+树所有关键字都会在叶子节点出现,叶子节点构成一个有序链表,而且叶子节点本身按照关键字的大小从小到大顺序链接。
结构-决定特性
1、B+ 树查询效率更稳定。因为 B+ 树每次只有访问到叶子节点才能找到对应的数据,而在 B 树中,非叶子节点也会存储数据,这样就会造成查询效率不稳定的情况,有时候访问到了非叶子节点就可以找到关键字,而有时需要访问到叶子节点才能找到关键字。
2、B+ 树的查询效率更高,这是因为通常 B+ 树比 B 树更矮胖(阶数更大,深度更低),查询所需要的磁盘 I/O 也会更少。同样的磁盘页大小,B+ 树可以存储更多的节点关键字。
3、不仅是对单个关键字的查询上,在查询范围上,B+ 树的效率也比 B 树高。这是因为所有关键字都出现在 B+ 树的叶子节点中,并通过有序链表进行了链接。而在 B 树中则需要通过中序遍历才能完成查询范围的查找,效率要低很多。
Hash索引
Hash索引结构
键值 key 通过 Hash 映射找到桶 bucket。在这里**桶(bucket)**指的是一个能存储一条或多条记录的存储单位。一个桶的结构包含了一个内存指针数组,桶中的每行数据都会指向下一行,形成链表结构,当遇到 Hash 冲突时,会在桶中进行键值的查找。
因为Hash是通过函数进行计算得出的,造成了hash无序且无规律的特性,适用场景比较少,当字段的重复度低,而且经常需要进行等值查询的时候,采用 Hash 索引是个不错的选择。
结构-决定特性
1、Hash 索引不能进行范围查询,而 B+ 树可以。这是因为 Hash 索引指向的数据是无序的,而 B+ 树的叶子节点是个有序的链表。
2、Hash 索引不支持联合索引的最左侧原则(即联合索引的部分索引无法使用),而 B+ 树可以。对于联合索引来说,Hash 索引在计算 Hash 值的时候是将索引键合并后再一起计算 Hash 值,所以不会针对每个索引单独计算 Hash 值。因此如果用到联合索引的一个或者几个索引时,联合索引无法被利用。
3、Hash 索引不支持 ORDER BY 排序,因为 Hash 索引指向的数据是无序的,因此无法起到排序优化的作用,而 B+ 树索引数据是有序的,可以起到对该字段 ORDER BY 排序优化的作用。