对于Mysql索引的理解

前言:

    对于数据库中的索引,一个非常好的类比是把数据库索引看作是书的索引。如果你有一本关于狗的书,你想要找关于‘黄金猎犬’的那部分。当你可以通过在书背的索引找到哪几页有关于‘黄金猎犬’信息的时候,你为什么要翻完正本书 - 这相当于数据库中的全表扫描。同样的,就像一本书的索引包含页码一样,数据库的索引包含了指针,指向你在SQL中想要查询的值所在的行。

    对于数据库也是一样,但是数据库更加复杂,因为其查询不仅会有等值查询(=),还有范围查询(>, < , between, in),like模糊查询,以及交集查询(AND),并集查询(OR)等等。

数据库索引:

    基于以上的分析,那么数据库应该采用何种方式来应对所有的问题呢?

    分段处理,可否将数据分段呢?假如有1000条数据,1-100分成第一段,101-200分成第二段...这样,如果我需要查询108条数据,则只需要去找第二段数据就好了,是不是节省了大量的查询时间呢?

    我们知道,在数据结构中,有二叉数的结构,查询的时间复杂度为O(logN),具有不错的查询性能,可我们知道如果采用这种数据接口作为索引的数据结构,那么索引数据就必须按照这种结构存储,而数据库的数据是保存在磁盘上的,我们不可能一次性将数据全部加载到内存中,只能是采用预读的方式,每次加载一部分数据到内存中。

I/O 和预读:

    Mysql数据库数据访问是基于磁盘的访问形式,而磁盘访问,每一次的磁盘IO的时间约为9ms,看似时间很短,但是我们要知道的是计算机执行指令的速度是远远快于磁盘IO的。

局部预读性原理:

    由于磁盘IO的高耗时操作,计算机系统做了很多优化,当一次磁盘IO时,不仅会读取当前磁盘地址的数据,还会把相邻的数据也一起读到内存中,因为一般情况下,其相邻的数据很快也会被访问到,这就是局部预读性原理。因此

    每一次磁盘IO读取的数据我们称为一页数据,不同的操作系统下,一页数据的大小不一定,一般为4K或者8K,即一页数据读取就是发生了一次IO操作。

索引数据接口:

对于Mysql索引的理解_第1张图片
1

B+树分析:

    所有真实数据存在与叶子节点

    淡蓝色方框表示一个磁盘块,每个磁盘块中包含几个数据项(深蓝色),和指针(黄色)

    非叶子节点不存储真实数据,只存储指引搜索方向的数据项,如17,35等数据并不是真实存在与数据表中的数据。

B+树的查找过程:

    如果我需要查询数据项29,那么首先会发生一次磁盘IO将磁盘块1加载到内存中, 此时发生了一次磁盘IO,然后在内存中再利用二分查找去确定出29在17和35之间,即定位到磁盘块1中的黄色的P2指针(实际上索引根节点会常驻内存中,故这一次的IO是不需要的)

    再利用P2指针指向的磁盘块3,将磁盘块3加载到内存中, 此时发生了第二次磁盘IO,再利用二分查找法确定29位于26和30之间,从而定位到磁盘块3中的P2指针

    再利用P2指针去加载磁盘块8到内存中,此时发生了第三次磁盘IO,同时,经过内存中的二分查找法定位到了真正需要寻找的数据项29,整个查找过程结束。

    整个过程中,一共经历了三次磁盘IO,而在真实的使用场景中,三层的B+树可以表示百万行的数据,试想一下,对于一个包含百万行数据的表数据查询,只需要三次磁盘IO,那么性能提升将是巨大的。

B+树的性质:

    通过上面的例子,分析一下B+树的基本性质。

    磁盘IO的次数取决于B+树的高度H,假设当前数据表的数据为N个,每个磁盘块的数据项的数量是M个,则树高 H = log(M + 1)N, 当数据量N一定的情况下,M越大,H越小,这样查询数据所需要磁盘IO次数就越小,查询性能就会越好,所以如何增加磁盘块中的数据项是关键。

    M = 磁盘块的大小/数据项的大小, 而磁盘块的大小我们知道是固定的,那如果每个数据项占的空间越小,是不是数据项的数量就越多呢?这也是为什么要求索引字段尽量小的原因,还有就是为什么Mysql中B+树要求把真实数据放在叶子节点而不是内存节点,就是为了增加每个磁盘块中的数据项的数量,为了降低整个B+树的高度,为了减少磁盘IO的次数。

Mysql索引分类:

    普通索引:最基本的索引即NORMAL

    唯一索引:与普通索引类型不同的是唯一索引的列值必须唯一,允许空值。

    全文索引:FullText ,仅适用于MyISAM引擎的数据表,只能作用于CHAR,VARCHAR,TEXT数据类型的列

    组合索引:将几个列作为一条索引进行检索,需要满足最左前缀匹配原则,直到遇到范围查询则停止匹配。对于等于,IN可以乱序,Mysql的查询优化器会帮你优化成满足索引被识别的形式。

Hash索引和B+树索引的区别:

    我们直到Hash索引的等值查询效率极高,可以理解为Map,但是存在的缺点是不够灵活,不能支持范围查询,比如查询10-100之间,因为HashMap作为索引结构的话,是无序的。另外当数据量大的时候,势必会存在Hash冲突。

    而B+树虽然在查询效率上没有Hash的效率高,但是B+树上的数据是有序的,其对于查找、删除、插入操作都可以可以在对数时间内完成

    故B+树作为常用的索引数据结构

你可能感兴趣的:(对于Mysql索引的理解)