mysql - 索引结构

432 阅读3分钟

索引结构:

  1. 数据存储: 聚簇索引、非聚簇索引
  2. 存储结构:b+tree、hash
  3. 逻辑: 主键索引、单列索引、联合索引、唯一索引、fullText等;
  4. 查询实现: 覆盖索引;

存储结构问题

hash和bTree索引的区别:

  1. hash更适合等值匹配;
  2. b+tree对范围查询和排序更有优势;
  3. 由于hash冲突的问题,如果值重复很多会造成hash索引效率降低;

b-tree的定义:

1. d是大于1的正整数,成为树的度;
2. 每个节点上的key的个数为n, d <= n <= 2d;
2. h 是树的高度;
3. 所有的叶子结点都处在同一个高度;

b+tree的优化:

1. 内节点不存储数据,只存储key,叶子结点不存储指针;
2. 且节点的存储为 左闭合区间;

为什么使用b+tree:

1. 其他的查询如: 顺序查询、二分查询、二叉树查询、红黑树等,这些结构的查询复杂度随着树层级的增高,导致磁盘io次数增大,不能很好的利用磁盘读取的特性;

2. 由于索引文件是存储在磁盘而不是内存中,所以减少对磁盘的io次数就能加快查询速度;而磁盘在读取数据的时候会顺便读取当前数据后面一页的数据并返回,称之为磁盘预读。
	通过设置b+tree的每一个节点存储大小为一页,而根据b+ tree的结构可知查询次数恒定为树高度H,因此查询复杂度稳定为O(logdN)。
	基于这些条件来看,树的出度d越大则查询的效率越高,而出度的上线是由节点的key和data的大小决定的,因此b+tree在内节点上去除了data,可以获得更大的出度。
3. b+tree 的叶子结点上存储了一个指向相邻节点的指针,提高了区间查询的性能;

b+Tree在不同引擎的实现:

  • myisam引擎: 叶子结点上存储的data是数据的地址; myisam的主键索引和辅助索引没有本质区别,仅仅保证的唯一性,是非聚集索引;

  • innoDb: 叶子结点上存储的data是数据; innodb的主键索引的data存储的是数据本身,可以说表数据本身就是一个大索引,是有顺序的索引-聚集索引,而且innodb建表如果没有制定索引,它会默认添加一个值作为主键索引的; innodb的辅助索引存储的data是主键id,通过普通索引查询到主键id,再通过主键索引查询出具体数据;

联合索引最左前缀匹配:

1. 理论上来说mysql是对where条件的顺序敏感的,不过在查询优化器的作用下,可能有一些重排序,
	比如 where条件中包含了索引中全部的列,此时顺序会被重排序成正确的顺序;
		where中包含了多个单列索引,但是只会选择一个索引查询,而选择的方式是优化器会判断索引的复杂度来选择索引执行;
2. 开头的不能丢 中间的不能断;
3. 对索引列不能够添加函数和操作符,但是可以添加like函数执行前缀匹配;
4. 索引支持范围查询,但是在范围查询字段右边的字段则不会用到索引,且索引中的范围列只能有一个;

索引的创建优化:

1. 索引的选择性,即索引列值的重复率越小越好; 计算公式: count(distinct(key1)) / count(1)
2. 使用前缀索引,如果索引前缀一部分就能够满足选择性的要求,则也可以是索引变小使得b+tree的节点存储容量变高,树高度降低;