-
主键索引
磁盘数据页的存储结构
- 数据库最终所有的数据(包括我们建的各种表以及表里的数据)都是要存放在磁盘上的文件里的,然后在文件里存放的物理格式就是数据页,大量的数据页是按顺序一页一页存放的,然后两两相邻的数据页之间会采用双向链表的格式互相引用。如下
- 然后一个数据页內部会存储一行一行的数据,也就是平时我们在一个表里插入的一行一行的数据就会存储在数据页里,然后数据页里的每一行数据都会按照主键大小进行排序存储,同时每一行数据都有指针指向下一行数据的位置, 组成单向链表。
没有索引的情况下查询
-
每个数据页里都会有一个页目录,里面根据数据行的主键存放了一个目录,同时数据行是被分散存储到不同的槽位里去的,所以实际上每个数据页的目录里,就是这个页里每个主键跟所在槽位的映射关系
-
所以假设你要根据查找一条数据,且表总共就一个数据页,首先就会先到数据页的页目录里根据主键进行二分查找,然后迅速定位到主键对应的数据是在哪个槽位里,然后到那个槽位里去,遍历槽位里每一行数据,就能快速找到那个主键对应的数据了。如果是其他字段,只能是根据数据页内部的单向链表来遍历查找,最终找到对应的数据
-
假如数据很多,有很多页,第一个没有,根据双向链表依次把磁盘上的数据页加载到缓存页里去,然后在一个缓存页内部来查找那条数据,然后按一样的方法在一个缓存页内部查找那条数据,然后循环,就是全表扫描
主键索引
- 把每个数据页的页号,还有数据页里最小的主键值放在一起,组成一个主键目录,然后后续你查询主键值,就可以在目录里二分查找直接定位到那条数据所属的数据页,接着到数据页里二分查找定位那条数据就可以了
-
但在数据很多很多的情况下,比如有几百万,几千万,甚至单表几亿条数据都是有可能的,这样就有有大量的数据页,然后主键目录里就要存储大量的数据页和最小主键值,这是后实际上是采取了一种把索引数据存储在数据页里的方式来做的,你的表的实际数据是存放在数据页里的,然后你表的索引其实也是存放在页里的,此时索引放在页里之后,就会有索引页,假设你有很多很多的数据页,那么此时你就可以有很多的索引页,此时如下图所示。
-
但是这是后你就有很多索引页,于是接下来我们又可以把索引页多加一个层级出来,在更高的索引层级里,保存了每个索引页和索引|页里的最小主键值,如下图所示。
- 如你最顶层的那个索引页里存放的下层索引页的页号也太多了,此时可以再次分裂,再加一层索引页,比如下面图里那样子,
- 所以主键索引,当你为一个表的主键建立起来索引之后,其实这个主键的索引就是一颗 B+树,然后当你要根据主键来查数据的时候,直接就是从B+树的顶层开始二分查找,一层一层往下定位,最终一直定位到一个数据页里,在数据页內部的目录里二分查找,找到那条数据。这就是索引的物理存储结构,采用跟数据页一样的页结构来存储,一个索引就是很多页组成的一颗B+树。