MySQL索引与存储引擎

MySQL索引与存储引擎

  • 一、索引
    • 1、MySQL索引选择的数据结构
      • 1.1、二叉树
      • 1.2、红黑树
      • 1.3、Hash
      • 1.4、B-Tree
      • 1.5、B+Tree
    • 2、联合索引
      • 索引的最左前缀原则
    • 3、索引的分类
  • 二、MySql存储引擎
    • 1、概念
    • 2、Myisam和InnoDB两种搜索引擎
    • 3、Myisam索引实现(非聚集索引)
    • 4、InnoDB索引实现
      • 4.1、InnoDB表必须有主键,并且推荐使用整型的自增主键
      • 4.2、非主键索引结构叶子节点存储的是主键值的原因

一、索引

索引是帮助MySql高效获取数据的排好序的数据结构,索引存储在文件里

当没有索引时,在执行一条Sql语句时是对一张表的逐条语句去比对查询结果的,有如下两个缺点:
(1)所有的记录都会比对,比对的量比较大。
(2)由于一张数据表的记录在磁盘上的位置不一定是相邻的,所以要进行多次的io操作,io操作是相当消耗性能的(因为数据表中的记录可能插入一条数据之后,过了很长时间才插入的下一条记录,然而磁盘上数据是按照磁道顺序记录的,所以数据表的记录不一定在磁盘上相邻)。

1、MySQL索引选择的数据结构

1.1、二叉树

MySql索引底层没有用二叉树作为索引的存储结构

(1)特点:节点左孩子比节点的值小,节点右孩子比节点的值大。
(2)简介:在使用这种数据结构时,就相当于是将数据简单排了个序,可以减少查找数据的次数。
(3)缺点:当数据是递增或者递减 的时候会出现成为了一个链表,这样降低了查找数据的性能。

1.2、红黑树

MySql索引底层没有用红黑树作为索引的存储结构

(1)特点:是一种自平衡二叉排序树,它属于平衡树。
(2)缺点:高度不可控,当一个表的数据量非常的大的时候,树的高度就很高,查找的次数就会变多,IO就会变多,也是非常消耗性能的。

1.3、Hash

MySql索引底层可以使用Hash作为索引的存储结构

Hash结构就是当查找一条数据时,先对条件进行Hash,然后将Hash后的值全部放入内存中做比对,如下图所示,只需做一个Hash并且将Hash后的所有值进行IO放到内存中进行比对即可,所以,在很多时候Hash的效率比B+Tree高,因为有可能一次hash之后就找到了想要的数据。
MySQL索引与存储引擎_第1张图片(1)hash表只能匹配是否相等,仅能满足“=”,“IN”,不能实现范围查找
(2)当需要按照索引进行order by时,hash值没办法支持排序。
(3)当数据量很大时,hash冲突的概率也会非常大
(4)使用B+树作为索引的组合索引可以支持部分索引查询,如(a,b,c)的组合索引,查询中只用到了a和b也可以查询的,如果使用hash表,组合索引会将几个字段合并hash,没办法支持部分索引

总结:Hash作为索引时,有很多特殊情况用不了,同时还要解决Hash冲突问题(需要额外的开销),所以一般我们还是使用B+树作为MySQL的索引。

1.4、B-Tree

MySql索引底层没有用B-Tree作为索引的存储结构

(1)树的高度是可控的,叶子节点的深度都是一致的,叶节点的指针为空。
(2)所有索引元素不重复。
(3)节点中的数据索引从左到右底层排序。(有序)

MySQL索引与存储引擎_第2张图片

B-Tree缺点
(1)非叶子节点也存储数据,存储的数据量有限。
(2)各个叶子节点之间不能相互访问。

1.5、B+Tree

(1)特点
①非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
②叶子节点包含所有索引字段
③叶子节点用指针连接,提高区间访问的性能
(2)简介:B+Tree是B-Tree一种升级变种,这里所展示的B+Tree是Mysql特有的,它在原本的B+Tree上做了许多的优化,使得存储的数据量变大,叶子节点之间也有了指针式的访问性,这里的双箭头是MySql优化的,原本的B+Tree是单箭头,详情如下图所示:
①原始的B+Tree:
MySQL索引与存储引擎_第3张图片②MySQL优化后的B+Tree:
MySQL索引与存储引擎_第4张图片

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

2、联合索引

一张表的多个字段组成的索引叫联合索引,就比如(name,age,position)

MySQL索引与存储引擎_第5张图片由上图可知,他是存储在B+Tree中的,则需要从左到右排好序,先从第一个字段排序,在按照第二个字段,再第三个字段

索引的最左前缀原则

在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配

3、索引的分类

一个索引只包含单个列,但一个表中可以有多个单列索引。

(1)普通索引(INDEX):允许索引列中有重复值和空值
(2)唯一索引(UNIQUE INDEX):不允许重复,但是允许为空值,
(3)主键索引(PRIMARY KEY):不允许重复和空值

二、MySql存储引擎

存储引擎(Storage Engine)是 MySQL 的专用称呼,面向的对象是数据库表

1、概念

MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。

如果我们在创建表的时候不指定,默认的存储引擎是innodb。

2、Myisam和InnoDB两种搜索引擎

MySQL索引与存储引擎_第6张图片(1)InnoDB和Myisam均是B+树作为索引
(2)InnoDB是聚集索引,叶节点包含完整的数据记录,数据文件是和索引绑在一起的。myisam是非聚集索引,叶节点不包含完整的数据记录,索引和数据文件是分离的,索引保存的是数据文件的指针;
(3)InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;Myisam的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。

3、Myisam索引实现(非聚集索引)

通过上图可知,Myisam存储引擎每张表对应在磁盘上有三个文件,.frm,.MYD,.MYI,所以,数据表的数据和索引是分开的,在查询数据时,需要先从索引去找,然后再连接另外一个文件查询数据,有点类似于回表的概念,详情如下图所示:
MySQL索引与存储引擎_第7张图片

4、InnoDB索引实现

(1)数据文件本身就是索引文件
(2)表数据文件本身就是按B+Tree组织的一个索引结构文件
(3)聚集索引-叶节点包含了完整的数据记录

(1)主键索引(聚集索引)
MySQL索引与存储引擎_第8张图片
(2)二级索引、辅助索引(非聚集索引)
MySQL索引与存储引擎_第9张图片

4.1、InnoDB表必须有主键,并且推荐使用整型的自增主键

(1)如果没有主键会怎么办?
答:则按照下列规则来建聚簇索引,没有主键时,会用一个唯一且不为空的索引列做为主键,成为此表的聚簇索引;如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。

(2)InnoDB为什么推荐使用自增ID作为主键?
答:自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。

4.2、非主键索引结构叶子节点存储的是主键值的原因

总结:一致性和节省存储空间:
(2)已经维护了一套主键索引+数据的B+Tree结构,如果再有其他的非主键索引的话,索引的叶子节点存储的是主键,这是为了节省空间,因为继续存数据的话,那就会导致一份数据存了多份,空间占用就会翻倍。
(1)另一方面也是一致性的考虑,都通过主键索引来找到最终的数据,避免维护多份数据导致不一致的情况。

你可能感兴趣的:(MySQL,mysql)