mysql对索引的定义为:
帮助MYSQL高效获取数据的一种数据结构。
行,表,文件
分析:
A.行存储在文件中。
B.行,表都是数据库的概念,操作系统并不知道这些逻辑。
C.MYSQL的MYISAM存储引擎会将一个表的数据存放至一个文件,而在默认情况下INNODB,
则会不同表的数据都会存储至一个文件。
D.每个文件可以划分为页。比如上图,就划分了5个页。
E.要添加数据时,MYSQL会在最后一页的最后一行插入数据,如果最后一页已经满了的话,
就需要新生成一页。
F.如上图,每个页里面都有空隙,那么这是怎么造成的呢?
根据E,肯定不是添加数据导致的。而是删除数据导致的。也就是说,删除导致了页的碎片。
那么为什么MYSQL不在添加的时候自动去填充这种空隙呢?如果一张表很大,
MYSQL每次添加数据都需要从上到下去找空隙,那么这就会有很大的延时。
G.一个页能有多少行?
比如一个页的大小为4KB,一行记录占用90字节的话,那么4*1024/90=45,也就是说
大概一页可以放置45条数据。页的大小是和操作系统和数据库相关的。
H.页是I/O的基本单位。
数据库不可能指示操作系统去拿到某些记录或者拿到几个字节的数据,只能告诉去加载
哪些页至内存,然后数据库在页中找到想要的数据。也就是说,一条记录应该由
页标示 + 行标示 共同构成这条记录的唯一标示。
索引是如何工作的?
如果一张表很大,有几百万行,每次都使用顺序逐行查找的话,势必效率低下。
而索引,这种数据结构,提供了查找表的另外一种方式。
看一个简化版的MYSQL索引:
【构建在上面图中表的no列】
A.索引的数据结构表现形式为一个多节点的树
B.有一个根节点
C.节点内的值是有序的
D.可以看到根节点的44的P1指向的节点的值都小于等于44.其实其他的节点
都是这样的。
E.节点中的指针PX,要么指向下一个节点,如P3,要么指向表中的记录,如P6.
对于P6这种指向表中记录的节点即为叶子
F.叶子是链接的,也就是说一个叶子指向下一个叶子
G.其实P6相当于 页标示 + 行标示
索引查找举例分析:
案例一:利用索引查找no=39的所有行
第一步,从根节点开始,此时根成为活动节点
第二步,判断活动节点是不是叶子,如果不是叶子,继续 第三步 ; 否则 继续
第四步
第三步,由于39<44,因此P1所指向的节点成为活动节点,继续 第二步
第四步,在活动节点中查找值,取出指针,也就是 这个值所在页的标示
第五步,数据库指示操作系统加载这些页,然后再在这些页中找到no=39的行
可见,查找特定的值的所有行,MYSQL利用索引,并不需要浏览所有行,可以快速找到。
案例二:获取按照no排序的所有行
直接查找叶子,先获取P6的所有页,然后是P7的所有页。
由于叶子后面还有叶子,因此下一个叶子继续上面的过程。
no=2的时候,需要取第二页
no=6的时候,需要取第一页
no=7的时候,需要取第三页
no=8的时候,需要取第四页
no=27的时候,需要取第二页
...
可以发现,由于文件中的行是没有顺序的,那么导致有些页必须多次获取,这会增加
处理时间。(内存中的页的个数是有限的,很可能有些页已经不在内存中,因此必须
重新从硬盘获取页)
为了加快这一过程,就必须文件中的行是有序存放的,那么就可能每个页只需要获取
一次,比如no=2在X页中,那么no=6就不需要再次获取页了,因为正确的页已经存在内存
中了,MYSQL是理解这一点的。