写点什么

MySQL 索引之基本概念

作者:java易二三
  • 2023-08-30
    湖南
  • 本文字数:1858 字

    阅读完需:约 6 分钟

什么是索引

MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。那么我们可以得出索引的本质:本质就是,索引是一种数据结构。索引的目的在于提高查询效率,可以类比字典。可以理解为:排好序的快速查找数据结构。 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。也就是说数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。

索引的优劣势

优势:

  • 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的 IO 成本。

  • 通过索引列对数据进行排序或分组,降低数据排序的成本,降低了 CPU 的消耗。

劣势:

  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE 和 DELETE。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件。每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息

  • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间 AVLTree 高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

索引的数据结构

BTree 索引

BTree 索引的数据结构是一棵 b 树,一个节点可以拥有多于 2 个子节点的二叉查找树,每个节点当作不同的磁盘块,那么每个磁盘块上包括几个数据项、指向关键字具体信息的指针、指向其他磁盘块的指针。


查找的过程:如果要查找数据项 29,那么首先会把磁盘块 1 由磁盘加载到内存,此时发生一次 IO,在内存中用二分查找确定 29 在 17 和 35 之间,锁定磁盘块 1 的 P2 指针,内存时间因为非常短(相比磁盘的 IO)可以忽略不计,通过磁盘块 1 的 P2 指针的磁盘地址把磁盘块 3 由磁盘加载到内存,发生第二次 IO,29 在 26 和 30 之间,锁定磁盘块 3 的 P2 指针,通过指针加载磁盘块 8 到内存,发生第三次 IO,同时内存中做二分查找找到 29,结束查询,总计三次 IO。

真实的情况是,3 层的 b 树可以表示上百万的数据,如果上百万的数据查找只需要三次 IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次 IO,那么总共需要百万次的 IO,显然成本非常非常高。

B+Tree 索引


B+Tree 与 B-Tree 的区别:

  • B-树的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。

  • 在 B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而 B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看 B-树的性能好像要比 B+树好,而在实际应用中却是 B+树的性能要好些。因为 B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比 B-树多,树高比 B-树小,这样带来的好处是减少磁盘访问次数。尽管 B+树找到一个记录所需的比较次数要比 B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中 B+树的性能可能还会好些,而且 B+树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用 B+树的缘故。  

B+Tree 的好处:

  • B+树的磁盘读写代价更低

  • B+树的查询效率更加稳定

聚簇索引与非聚簇索引

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据

非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam 通过 key_buffer 把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在 key buffer 命中时,速度慢的原因

innodb 中,非聚簇索引又称辅助索引,辅助索引访问数据总是需要二次查找。辅助索引叶子节点存储的不再是行的物理位置,而是主键值。

MySQL 索引分类

  • 主键索引:设定为主键后数据库会自动建立索引,innodb 为聚簇索引

  • 单值索引:即一个索引只包含单个列,一个表可以有多个单列索引

  • 一索引:索引列的值必须唯一,但允许有空值

  • 复合索引:即一个索引包含多个列

索引的使用场景

需要创建索引:

  • 主键自动建立唯一索引

  • 频繁作为查询条件的字段应该创建索引

  • 查询中与其它表关联的字段,外键关系建立索引

  • 单键/组合索引的选择问题, 组合索引性价比更高

  • 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

  • 查询中统计或者分组字段

不要创建索引:

  • 表记录太少

  • 经常增删改的表或者字段。

  • Where 条件里用不到的字段不创建索引

  • 过滤性不好的不适合建索引

用户头像

java易二三

关注

还未添加个人签名 2021-11-23 加入

还未添加个人简介

评论

发布
暂无评论
MySQL索引之基本概念_Java_java易二三_InfoQ写作社区