Mysql系列一(存储引擎)
1.引言:
说起存储引擎第一感觉就是很高大上,在mysql5.1版本之前,默认的存储引擎是MyISAM,在5.5版本InnoDB才成为默认的存储引擎,可能是被oracle收购了,并加以优化。
2.InnoDB:
现在InnoDB已经是默认的事务型存储引擎了,也是最重要、使用最广泛的存储引擎,想要真正了解InnoDB,可能说上几天都说不完,它主要是被设计来处理大量的短期事物(short-lived),短期事物大部分情况是默认提交的,很少会被回滚,前面也说了,存储引擎负责数据的真正存取,同时InnoDB的数据文件本身也是索引文件。
2.1 InnoDB存储数据的结构:
我们都知道,mysql的数据是存储在磁盘上,那么我们平时用的表,表里面那么多的数据都是如何存储的呢?其实InnoDB是按照B+Tree数据结构存储的数据,什么是B+Tree?他的结构怎么样呢?
2.1.1 B+Tree:
B+树是为磁盘或其他直接存取辅助设备而设计的一种平衡查找树(如果不知道平衡查找树,请自行百度),在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶节点中,各叶节点指针进行连接。
借图:
从图中可以看出,这棵树的深度为3层,深度越深表示数据可能越多,每一层由数量不定的节点组成,每一个非叶子节点(叶子节点就是最后一层的节点,他就是是最小的,再没有子了)都有指向下一级子节点的指针和主键值,那么叶子节点和叶节点有什么不同么?叶子节点上除了主键外还保存了每行数据的除主键外的其他列数据,并且每个叶子节点都指向下一个叶子节点,从图中可以看出134节点指向567节点,这种结构的好处就是,按照主键的检索会非常快,并且主键范围检索也会很快, 其实这里说的节点是一个个数据页组成的,每个数据页默认大小是16k,每个数据页里面存放了多条记录,可能是100条货200条,具体看数据量的大小,按照数据页存储主要是减少了很多和磁盘的IO交互耗时,关于数据页,如果大家想要详细了解,请自行学习,或者博主会在后续的博客中来详解,这里就不多做赘述了。
下面看一个更直观的结构图:
我们知道了InnoDB是按照b+tree的方式存储数据的,并且是按照主键的顺序来存储的,那么是不是也可以这样理解,这个b+tree的结构是一个主键索引,他按照b+tree的方式来存储,在存储存储主键的同时也把表数据存储在子节点上面,ok,这里面提到了主键索引,主键索引属于一级索引,还有二级索引,下面详细介绍一下。
2.1 聚簇索引和非聚簇索引:
说起一级索引和二级索引,必须说的是聚簇索引和非聚簇索引。
聚簇索引:数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。因而在那些包含范围检查(between、<、<=、>、>=)或使用group by或orderby的查询时,一旦找到具有范围中第一个键值的行,具有后续索引值的行保证物理上毗连在一起而不必进一步搜索,避免了大范围扫描,可以大大提高查询速度。
非聚簇索引:叶级页指向表中的记录,记录的物理顺序与逻辑顺序没有必然的联系。非聚簇索引则更像书的标准索引表,索引表中的顺序通常与实际的页码顺序是不一致的。
从聚簇索引和非聚簇索引的定义中可以看出,mysql的主键索引属于聚簇索引,其他的自建的普通索引属于非聚簇索引,也就是二级索引,二级的结构也是一颗b+tree,但是他的叶子节点存储的不是表数据,key-value的value值保存的是主键id的值,这样的结构在使用二级自建索引时候,第一步是先遍历找到对应节点中的主键值,在通过主键值去主键索引寻找对应的真是数据,这样做的话,相当于存储了多次的主键,所以我们的innodb引擎,主键值要尽量小,比如自增的long类型字段,很长的string类型的比如,拿身份证来当主键会很浪费性能,同时使用二级索引也会经历两次寻址,比直接存储物理地址指针慢。我们看下两个主流引擎之间一级、二级索引的对比图:
2.2.索引的管理:
索引在创建或者删除时,MySQL会先创建一个新的临时表,然后把数据导入临时表,删除原表,再把临时表更名为原表名称。
但是在InnoDB Plugin版本开始,支持快速创建索引。其原理是先在InnoDB上加一个s锁,在创建过程中不需要建表,所以速度会很快。创建过程中由于加了s锁,所以只能进行读操作,不能写操作。
show index form table;是查看表中索引的信息的。
Table:索引所在的表名
Non_unique:非唯一的索引,可以看到primary key 是0,因为必须是唯一的
Key_name:索引名称
Seq_in_index:索引中该列的位置
Column_name:索引的列
Collation:列以什么方式存储在索引中。可以是A或者NULL,B+树索引总是A,即排序的。
Cardinality:表示索引中唯一值的数目的估计值。如果非常小,那么需要考虑是否还需要建立这个索引了。优化器也会根据这个值来判断是否使用这个索引。
Sub_part:是否是列的部分被索引。100表示只索引列的前100个字符。
Packed:关键字如果被压缩。
Null:是否索引的列含有NULL值。
Index_type:索引的类型。InnoDB只支持B+树索引,所以显示BTREE