首先我们从B树讲起
B树
B树又称多路平衡查找树,那为什么树要长这样呢?
通常情况下,一棵树的数据量比较庞大,不能一次性全部读入内存。所以需要分批读入,可以理解为一层一层的读入,那么就要减小树的高度
一个m阶的B树具有如下几个特征:
- 根结点至少有两个子女
- 每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
- 每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
- 所有的叶子结点都位于同一层。
B+树
一个m阶的B+树具有如下几个特征:
- 有k个子树的中间节点包含有k个元素,每个元素不保存数据,只用来索引,所有数据都保存在叶子节点(可以存储更多的指针,树高更小)
- 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接
- 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素(最大的元素永远在根节点)
在B-树中,无论中间节点还是叶子节点都带有卫星数据。
而在B+树当中,只有叶子节点带有卫星数据,其余中间节点仅仅是索引,没有任何数据关联。
卫星数据,指的是索引元素所指向的数据记录,比如数据库中的某一行
B+树的查询必须最终查找到叶子节点,而B-树只要找到匹配元素即可
B+树一般需要3~4次的查询
B+树的优势:
- 单一节点存储更多的元素(这样该节点下分支变多了,树变矮胖了),使得查询的IO次数更少
- 所有叶子节点形成有序链表,便于范围查询
哈希索引
自适应哈希
InnoDB存储引擎会监控对表上各索引页的查询。如果观察到建立哈希索引可以带来速度提升,则建立哈希索引,称之为自适应哈希索引(Adaptive Hash Index, AHI)。当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。
BitMap
- 只适用于某个字段只有固定的几个值
- mysql不支持位图索引
RowId | 1 | 2 | 3 | 4 | 5 | … |
---|---|---|---|---|---|---|
男 | 1 | 0 | 1 | 0 | 0 | |
女 | 0 | 1 | 0 | 1 | 1 |
聚簇索引
- InnoDB的主键采用聚簇索引存储,使用的是B+Tree作为索引结构,叶子节点存储的是索引值和数据本身
- InnoDB的二级索引不使用聚蔟索引,叶子节点存储的是KEY字段加主键值。因此,通过二级索引查询首先查到是主键值,然后InnoDB再根据查到的主键值通过主键索引找到相应的数据块
innodb所采用的索引结构。聚簇索引特点是存储数据的顺序和索引顺序一致,聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针
- MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址,查询只能查到指针地址,再由地址去查数据
- InnoDB的数据文件本身就是索引文件。表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录,InnoDB表数据文件本身就是主索引。
InnoDB的每一个表都会有聚集索引:
- 如果表定义了PK,则PK就是聚集索引;
- 如果表没有定义PK,则第一个非空unique列是聚集索引;
- 否则,InnoDB会创建一个隐藏的row-id作为聚集索引;
为什么innodb使用聚簇索引结构?
- 减少了出现行移动或者数据页分裂时二级索引的维护工作(当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引),因为他是基于主键值来存储的
- 根据主键查询快
- 非聚簇索引的表数据在磁盘的存储顺序与索引顺序无关
联合索引的最左匹配原则
索引查询会一直向右匹配,直到遇到范围查询(< > between like)就停止匹配
- 比如有查询:a=3 and b=4 and c>5 and d=6,
- 如果建立a,b,c,d顺序的联合索引,不会走d字段的索引
- 如果建立a,b,d,c的索引则都可以用到,a,b,d的顺序可以任意调整,mysql的查询优化器会帮你优化成索引可以识别的形式
联合索引原理
索引与like
当我们对字段a建立索引时
- like keyword% 索引有效
- like %keyword 索引失效,使用全表扫描。但可以通过翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全表扫描
- like %keyword% 索引失效,也无法使用反向索引