数据库索引的原理

我们从盘古开天辟地讲起

1、首先数据库中的数据是以什么样的形式存储在我们的设备中呢?

一个表是由几个字段的数据组成,虽然我们看上去这些数据都有序地、“一行一行地”存在表中。但是事实上,物理存储中的这些数据可能分散在不同的数据块中。比如(id=1, name='martin',age=22,sex=1),要找到martin这个人的信息,在查找的时候先找到第一个数据(id=1)所在的数据库地址,然后在这个数据的底端找到下一个数据块的地址(name='martin'的地址),类似于链表的结构。如果我们查找的数据量比较大,显然这种方法是不合适的。所以出现了索引,索引是对表中的字段在另开辟的空间中建立一种新的数据结构(B/B+树,有的数据库也用哈希桶)保存这些值,对这些值进行排序,每个值又指向其相关的值。没有索引的情况下,数据可能一整块一整块地存储在磁盘上;但是加了索引之后,表在磁盘上的存储结构就由整齐排列的结构转变为树状结构。

 

2、再讲讲B树和B+树

我们都知道二叉树这个可以将查询范围每次缩小1/2的数据结构。尽管这个效率已经非常可观,我们为什么还要用B树和B+树作为数据库索引的存储结构呢?我们上边说到,在没有索引的情况下数据库中的数据可能一块一块地存储在硬盘上,而硬盘是顺序存取设备,硬盘中需要磁头先定位再存取,这就造成了就近读取速度快一些。二叉树在满的情况下,每个节点仅有两个孩子节点,这就容易造成节点两端的深度不一致,可能某一端数据比较多,比较深。而我们查询时需要先通过IO操作将数据加载到内存中,而数据不能一次性全部加载到内存中,只能逐一加载每个磁盘页(对应树的一个节点),二叉树深度过大就会造成磁盘io操作频繁效率低下,而B树和B+树这类平衡树能保证节点两边树的深度相同,并且每个节点能存储多个元素,降低了深度,也就减少了IO操作。

(PS:1、MySQL底层是B+树,Oracle是B树,其他也有一些数据库使用是哈希桶。2、磁盘适合B树结构存储,内存适合Hash存储,因为内存是随机访问随机存储的存储设备,不需要磁头定位)

 

3、索引具体存储了啥?

上面说过索引是对表中的某些字段在另开辟的空间中建立的一种新的数据结构。那么索引有哪些数据组成呢?一条索引中包含的基本信息包括键值(即你定义索引时指定的所有字段的值)+逻辑指针(指向数据页或者另一索引页,索引页就是存储索引的空间)。索引页中的数据量比真实数据小许多,也密集许多,所以在索引中查找时在io上占很大优势。

B树的非叶子节点对应了索引页,叶子节点对应了数据页。

 

4、索引有哪些类型?

索引分为聚集索引非聚集索引。比方说我们经常给表的id字段加上主键,主键就是一个聚集索引(当然,创建主键的时候可以声明为非聚集索引。主键必须依赖于索引,伴随这所以的主键不能删除,除非同时删除主键。一个表也只能有一个聚集索引,因为真实数据的物理存储只可能是一种;如果一张表没有索引,那么它被称为堆集,这样的表中数据行没有特定的顺序,所有的的新行都将被添加到末尾位置),它将整个表变成了一个索引,表中的所有数据就以平衡树的形式存储,所以一个表只能有一个主键。举个例子,有一万条数据,在没有主键索引之前,最坏的情况可能需要一万次IO操作、匹配才能查到结果,但是在B树的情况下,只需要匹配树的深度次数即可。当然,索引也有副作用。索引让查询速度上升,但是会让写入速度下降,因为平衡多叉树必须实时维持一个正确的姿态,增删改都会影响这棵树各节点的内容,破坏树的结构。因此在每此改变数据时,树的结构就需要改变,这个开销不可避免。

而非聚集索引就是我们平时提起和使用的常规索引,也是采用平衡树作为索引的数据结构。每新建一个索引就会将表中的数据拷贝一份(对于主键这个聚集索引,索引和表数据是一起存储的,并不会单独拷贝一份作为索引数据,不然也太蠢了),比方说我们给name字段加上索引,那么这个索引仅有name字段的值构成。

聚集索引和非聚集索引的区别在于:1、聚集索引表数据按照索引的顺序存储,叶子节点存储了真实的数据行,不再有另外单独的数据页;而非聚集索引表数据存储顺序与索引顺序无关,叶节点包含了索引的字段值以及指向数据页数据行的逻辑指针。2、通过聚集索引可以查找到我们需要查找的数据,而通过非聚集索引可以查找到记录对应的主键值,再通过主键值来定位数据。可以这么说:主键是通往真是数据的唯一途径。但是有一种情况不需要通过主键定位,就是覆盖索引。比方说我们给name和age加上索引,那么执行 select age from table where name = 'martin' 的时候,由于age也在索引中,所以不需要再通过主键来定位了。

 

参考博客

https://www.cnblogs.com/aspwebchh/p/6652855.html

https://www.cnblogs.com/lj820403/p/7246657.html

https://kb.cnblogs.com/page/45712/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章