磁盘数据页的存储结构

  1. 数据库的数据存放到磁盘上,文件存放的物理格式是数据页。数据页存放不是按顺序一页一页存放的,而是两两相邻的数据页会采用双向链表的方式互相引用。
  2. 数据页在磁盘文件里就是一段数据,数据页有一个指针指向上一个数据页在磁盘文件里的起始物理位置,还有一个指针指向自己下一个数据页的物理位置。
  3. 数据页内部存储数据,每一行数据会按主键大小进行排序存储,每一行数据都有指针指向下一行数据位置,组成单项链表。

image.png

没有索引,数据库是如何查询的

  1. 每个数据页都会有个页目录,里面根据数据的主键存放,主键—->槽位数据。
  2. 如果根据主键查询数据,在数据页的页目录里根据主键进行二分查找,如果根据非主键数据,只能一个数据页一个数据页遍历查询,最差可能全表扫描。

    不断插入数据是怎么进行页分裂的

  3. 有一个数据页,里面有数据组成单项列表。不停的往里面插入数据,需要再加一个数据页,需要保证后一个数据页的主键值要大于前一个数据页的主键值,这是索引运行的一个机制。

  4. 如果主键是自增的,可以保证后一个主键值大于前一个数据页主键值。如果是非自增,此时会出现一个页分裂的过程,就是在增加一个新的数据页的时候,会把前一个数据页里主键值较大的挪到新的数据页来,把插入比较小的主键值放到上一个数据页里去。

    基于主键的索引是如何设计的

  5. 如果没有索引,要查id=10的数据还是不好找,只能通过全表扫描。针对主键设计索引,其实就是主键的目录。把每个数据页的页号,还有数据页里最小的主键值放在一起,组成一个索引,在主键索引里使用二分法查询到满足条件的值。

image.png

如何用B+树实现索引的页存储物理结构

  1. 如果表里有很多数据,会有大量的数据页,然后主键目录里要存储大量的数据页和最小主键值,所以把索引数据也存储在数据页中,作为索引页。
  2. 如果有很多的索引页,要找到某个索引还是不容易,所以把索引页多加了一个层级,在更高的索引层级里,保留了每个索引页和索引页里的最小主键值。
  3. 比如要查id=46,先到顶层的索引页35通过二分法查找到索引页20,继续在索引页20里二分查询到数据页8,在数据页8里继续二分查询到id=46的。
  4. 如果顶层的索引页存放的下层索引页过多就再次分裂,再加一层索引页。这就是一个B+树。

image.png

聚簇索引

  1. 索引内部,对于一个层级内的索引页,互相之间都是基于指针组成双向列表。
  2. 聚簇索引就是一个B+树索引数据结构里,叶子节点就是数据页本身。
  3. InnoDB存储引擎里,对数据进行增删改查,就是把数据页放在聚簇索引里,数据在索引里,插入数据就是在数据页里插入数据。数据页分裂的时候,会调整各个数据页内部顺序,保证下一个数据页的所有主键值大于上一个数据页主键值。
  4. 数据量很大的话就一直抽取索引页分级。

    除主键之外的二级索引如何运作

  5. 对主键外的其他字段建立索引,比如name,age。 简单说就是插入数据的时候,一方面会把完整数据插入到聚簇索引的叶子节点的数据页中,同时维护好聚簇索引,另一方面为其他字段建立的索引,重新维护一个B+树。

  6. 如果基于name字段建立索引,插入数据的时候,会重新生成B+树,叶子节点是数据页,但是这个数据页里仅仅放主键字段和name字段。整体的规则跟主键索引一样,叶子节点naem值按大小排列。
  7. 如果查找的话,从name字段的索引按照二分法一级一级往下查找,一直找到叶子节点。此时需要”回表”,因为name索引树的叶子节点是主键值,所以需要回表根据主键值 去主键索引树里的叶子节点找到完整的数据。
  8. 一般name这种普通字段的索引称为二级索引。
  9. 联合索引同理,如果是name+age。叶子节点的数据页放id+name+age,先按name排序,name一样就按照age排序。

    插入数据时是如何维护B+索引树的

  10. 数据表最开始就是一个数据页,插入数据就直接在数据页里插入。数据页内部有一个基于主键的索引。表数据越来越多后,数据页进行分裂,数据进行挪动,保证第二个数据页的值都大于第一个数据页。根页升级索引页,里面有两个数据页的页号和最小主键值。 依次类推,数据越来越多,数据页越来越分裂,索引页也会分级。

  11. 二级索引同理,插入数据的时候,一方面在聚簇索引里插入数据,一方面在name字段的索引B+树唯一的数据页里插入。数据越来越多,name的索引树会分裂,升级。name字段的索引树不仅存放页号和最小name字段值,还有存放最小name的主键值,为了当name一样的时候,根据主键值区分。

    一个表里不是索引越多越好

  12. 建立索引可以提高性能

  13. 索引过多的话,建立很多的索引树,会占用磁盘空间。同时进行增删改的时候,需要保证B+树内部是有序的,不停的增删改会不停的挪动,效率会降低。