假设我们有很多数据页,然后我们想要根据主键来查询数据,假设你要搜索id=4的数据,我们如何查找到这个主键id=4的数据呢?全表扫描一个一个的去查找?显然不现实。所以我们需要针对主键设计一
![](https://i-blog.csdnimg.cn/blog_migrate/a44ba4a47ae0aa1e34f0e4f2dacf8fb5.png)
个索引。针对主键索引实际上就是主键目录,这个主键目录就是把每个数据页的页号,还有数据页里最小的主键值放在一起,组成一个索引的目录。
![](https://i-blog.csdnimg.cn/blog_migrate/b26091dec1e3ba8f4013fb31bc240ff7.png)
现在我们根据主键目录去查询就方便了,直接就可以到主键目录里去搜索,比如你要找id=3的数据,此时就会跟每个数据页的最小主键来比,首先id=3大于数据页2里的最小主键值1,接着小于数据页8里的最小主键值4。所以既然如此,你直接就可以定位到id=3的数据一定是在数据页2里了。
假设你有很多数据页,在主键目录中就会有很多的数据页和最小主键值,此时你完全可以根据二分查找的方式来找到你要找的id到底在哪个数据页里。所以这个效率是非常之高的,而类似上图主键目录就可以认为是主键索引。
实际生产环境中数据页都是一坨一坨的连续数据放在很多的数据页的,所以只要你能够根据主键索引定位的到数据所在的数据页,此时假设我们有别的存储方式存储了数据页跟磁盘文件的对应关系,此时你就可以找到一个磁盘文件。而且我们假设数据页在磁盘文件里的位置就是offset偏移量,你也是可以知道的,此时就可以直接通过随机读的方式定位到磁盘文件的某个offset偏移量的位置,然后就可以读取连续的一大坨数据页了。
随着业务量的不断发展,表中的数据量打到百万级,千万级。所以此时会有大量的数据页,然后你的主键目录里就要存储大量的数据页和最小值。这怎么行?实际上是采取了一种把索引数据存储在数据页里的方式来做的,也就是说,你的表的实际数据是存放在数据页里的,然后你表的索引其实也是存放在数据页里的,此时索引放在页里之后,就会有索引页,假设你有很多的数据页,此时你就可以有很多的索引页。
![](https://i-blog.csdnimg.cn/blog_migrate/13e9e4c9d2142881e624ea27eda82110.png)
但是现在又会有一个问题,现在很多索引页,但是此时你需要知道,你应该到那个索引页里去找你的主键索引,是索引页20?还是索引页28?这也是个大问题。
于是接下来我们又可以把索引页加一个层级出来,在更高的索引层级里,保存了每个索引页和索引页里的最小主键值。
![](https://i-blog.csdnimg.cn/blog_migrate/bb5318517a4c7fcf98e0c123aeb30fd2.png)
假设我们查找id=46,最先到最顶层的索引页35里去找,直接通过二分查找可以定位到下一步应该到索引页20里去找,接下来到索引页20里通过二分查找定位,也很快可以定位到数据应该在数据页8里,在进入数据页8里,就可以找到id=46的那行数据。
如果顶层的那个索引页存放的下层索引页的页号也太多了,此时就可以再次分裂,再加一层索引页。随着
![](https://i-blog.csdnimg.cn/blog_migrate/8f4ee9e6908d627be80c529ec10023c4.png)
数据页的不断增多,索引页层级也会随之不断变高,慢慢的索引页就会像一棵树----B+树。属于数据结构里的一种树形数据结构,所以一直说mysql的索引是用B+树来组成的。这个就是索引最真实的物理存储结构,采用跟数据页一样的页结构来存储,一个索引就是很多页组成的一刻B+树。
*****其实最下层的索引页,都是会有指针引用数据页的,所以实际上索引页之间跟数据页之间是有指针连接起来的。
![](https://i-blog.csdnimg.cn/blog_migrate/5ff3e5ddd6fb0864ccc3ebc2761bdc3a.png)
*****索引页自己内部,对于一个层级内的索引页,互相之间都是基于指针组成双向链表的。就跟
![](https://i-blog.csdnimg.cn/blog_migrate/f57356acfd0ab9da91993627aab6fc85.png)
数据页自己组成双向链表是一样的。当你把索引页和数据页连起来一起看的时候,它们就如同一颗完整的B+树,从根索引页88开始,一直到所有的数据页,其实组成了一颗巨大的B+树。在这颗B+树里,最底层的一层就是数据页,数据页就是B+树的叶子节点。所以,如果一颗大的B+树索引数据结构里,叶子节点就是数据页自己本身,那么此时我们就可以称这颗B+树索引为聚簇索引(索引页+数据页=B+树=聚簇索引)。
在InnoDB存储索引中,你在对数据增删改查的时候,就是直接把你的数据页存放在聚簇索引里的,数据就在聚簇索引里,聚簇索引包含了数据。如果你的数据页发生了页分裂,他此时会调整各个数据页内部的行数据,保证数据页内部的主键值都是有顺序的,下一个数据页的所有主键值大于上一个数据页的所有主键值。同时在页分裂的时候,会维护你的上一层索引页数据结构,在上一层索引页里维护你的索引条目,不同的数据页和最小主键值。
这个聚簇索引默认是按照主键来组织的,所以你在增删改查数据的时候,一方面会更新数据页,另一方面会给你自动维护B+树结构的聚簇索引,给新增和更新索引页,这个聚簇索引默认就会给你建立起来。
借道友法力一用:
![](https://i-blog.csdnimg.cn/blog_migrate/25abaacc5172d5fae184bb2c911c135e.png)
========================== stay hungry stay foolish =============================