我们需要想一下的是,什么是索引?索引会不会是一个文件,会不会是一种数据结构,如果是一种数据结构,那又会是什么类型的数据结构?我们使用索引的目的就是快速找到目标数据,减少对IO的操作,节省自资源,杜绝浪费。
先来了解几种数据结构:
1.二叉树数据结构:https://www.cs.usfca.edu/~galles/visualization/BST.html
可以看到二叉树是线性的,从上往下的层数就会越来越高,找到目标数据要进行的IO操作就要非常的高,假如要找007就要每个节点都找一次。
2.红黑树的数据结构:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
相对于二叉树来说,红黑树是做了一个旋转,层数是变少了,但是随着数据量的增大,层数也是会越来越高,查找到目标数据也是很费时间。
3:B+Tree的数据结构:https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html
B+Tree选择一个合适的度数来演示,建议是控制在3-5层(没有强制要求,Degree越高数据的层数就越低,即理想情况下所有数据无限大放在一层),可以看到每个节点(每一个框)里面是可以存很多的数据的,假如一层有多个节点,每个节点有多个数据,层层相乘就是一个很大的存储体积,而且层数不会太高。
到这里就可以明显的知道为什么MySql的索引使用的是B+Trees这种数据结构
到这里可能会有疑问,到底MySql的索引是如何实现的?
先来创建两张表:一个是用InnoDB作为引擎的表,一个是以MyISAM作为引擎的表(MySql的引擎是表级别的,不用的表可以有不同的engine)
CREATE TABLE `InnoDbTest` (
`id` int NOT NULL AUTO_INCREMENT ,
`name` varchar(255) NOT NULL ,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8
;
CREATE TABLE `MyISAMTest` (
`id` int NOT NULL AUTO_INCREMENT ,
`name` varchar(255) NOT NULL ,
PRIMARY KEY (`id`)
)
ENGINE=MyISAM
DEFAULT CHARACTER SET=utf8
CHECKSUM=0
DELAY_KEY_WRITE=0
;
查看生成的数据文件:
可以看出使用InnoDB作为引擎的表生成的是两个文件,使用MyISAM作为引擎的表生成的是三个文件
MyISAM中,MYI文件是描述表结构的一些index信息,MYD是存储数据的文件,frm是存储一些元数据的描述信息
InnoDB中,frm是存储一些元数据的描述信息,ibd是存储索引以及表数据的
下图是MyISAM引擎的,假如在id上建立索引,就会在MYI文件中生成一颗以ID为为索引的B+Tree树,通过叶子节点的记录的地址值来寻址找到数据,对应的sql语句就是:select * from table where id = 1,id是普通索引,如果是以name为索引也是同样的道理,也是会在MYI文件中生成一个以name的B+Tree索引树,对应的sql语句就是:select * from table where name = zhangsan,以MyISAM引擎的,下面建立的id或者以name为索引的,都是非聚集索引。
下图是InnoDB引擎的,以InnoDB作为引擎的表一般都是有主键的,这一类以主键为索引来组织数据的称为聚集索引。可以看出索引和数据是在一起的,都在叶子节点上,找到主键就找到数据。对应的sql语句就是:select * from table where id = 1,id主键索引。假如要在下面的InnoDB基础上的表建立一个以name的索引,它是这样的:其中绿框的1,2,3是主键值,通过记录的主键顺推去左边的图去找到数据