Mysql的InnoDB引擎-5.索引(2)
B+树索引
B+树索引的本质就是B+树在数据库中的实现。但是B+树索引在数据库中有一个特点就是高扇出性,因此在数据库中,B+树的层高一般都在2~4层,意味着查询某一个键值的行记录最多需要2~4次IO。B+树索引分为聚集索引和辅助索引。
聚集索引
聚集索引就是根据数据表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的行记录数据,也将聚集索引的叶子节点成为数据页。
聚集索引的存储并不是物理结构上连续的,而是逻辑上连续的。
- 页是通过双向链表连接,页按照主键的顺序排序。
- 每个页中的记录也是通过双向链表进行维护的,物理存储上可以同样不按照主键存储。
辅助索引
辅助索引也称为非聚集索引,叶子节点并不包含行记录的全部数据。叶子节点除了包含键值之外,每个叶子节点中的索引行中还包含了一个书签。
该书签是用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据,存储的具体内容是聚集索引的键。
辅助索引的存在并不影响数据在聚集索引的组织,所以每个表可以创建多个辅助索引,当通过辅助索引查询数据的时候,InnoBD先通过辅助索引查询到主键索引的主键,然后再通过主键索引来找到一个完整的行记录。
索引管理
通过Alter table或者create/drop index 创建或者删除索引。查看某个表的索引可以通过 show index from table_name,结果如下图:
- Table:索引所在的表名
- Non_unique:非唯一索引,primary_key为0,如果是非唯一索引值为1
- Key_name:索引的名字
- Seq_in_index:索引中该列的位置
- Column_name:索引列的名字
- Collation:列以什么方式存放在索引中,可以是A或者NULL。B+树索引是A,即排序的。NULL表示非排序的(比如自适应Hash索引)
- Cardinality:表示索引中谓一致的数据的预估值。Cardinality / 表行数尽可能接近1,如果非常小,这个索引的意义就很小。
- Sub_part:是否是列的部分索引,如果不为NULL,表示对某一列的前N个字符进行索引。
- Packed:关键字如何被压缩。如果没有压缩,NULL
- NULL:是否索引列含有NULL值,如果是yes,表示可以允许NULL值
- Index_type:索引类型,InnoDB只支持B+树索引
- Comment:注释信息
Cardinality
Cardinality值表示索引中不重复记录数据的预估值。Cardinality/n rows in table应该尽可能的接近1。
统计Cardinality是通过采样的方法完成的。Cardinality统计信息的更新发生在Insert或者Update操作中,但是并不是每次都会更新。更新策略为:
- 表中1/16的数据已经发生过变化。
- stat_modified_counter>2000000000 (stat_modified_counter用来记录发生变化的次数)
Cardinality采样是根据索引的8个叶子节点进行采样,然后通过8个节点预估出所有叶子节点的总和,得到Cardinality值,所以每次得到的值都不是准确不变的。
计算公式 Cardinality = (P1+P2+....+P8)* A/8 P为采样的节点1~8,A为叶子节点数量。
注意:如果表足够小,那么表的索引叶子节点小于或者等于8,那么每次计算的值就会相同。
Index的其他内容
Fast Index Creation
5.5之前Mysql数据库对于索引的添加或者删除这类的DDL操作,过程为:
- 首先创建一张临时表,表结构为通过alter table新定义的结构
- 然后把原表数据导入到临时表
- 接着删除原表
- 最后把临时表命名为原来的表名
如果对一个很大的表进行这样的操作,非常损耗性能。所以出先了Fast Index Creation(FIC)的索引创建方式。
对于辅助索引的创建,在对应的表加上S锁。创建索引过程中不需要重建表,删除索引只要更新内部视图即可,并将辅助索引的空间标记为可用,同时删除Mysql数据库内内部视图上对该表的索引定义即可。
注意:临时表创建的目录是通过tmpdir参数设置,要保证有足够空间创建临时表。FIC操作的时候,加了S锁,所以这个时候只能对数据进行读操作。
Online Schema Change
在线架构改变(OSC)过程:
- init:初始化阶段,验证工作,是有有主键外键触发器等验证
- createCopyTable:创建一个和原表一样的新表
- alterCopyTable:对创建新表进行alter操作,比如新增索引或者列等
- createDeltasTable:创建deltas表,为了创建触发器使用,之后对原表的DML操作会被记录deltas中。
- createTriggers:创建触发器。触发操作产生的记录被写入deltas表中。
- startSnpshotXact:开始OSC操作的事务。
- selectTableIntoOutFile:将原表数据写入新表(为了减少锁定原表的时间,通过分片将数据输出到多个外部文件,默认分片500000)
- dropNCIndexs:导入新表前,删除新表中的所有辅助索引
- loadCopyTable:将导出的分片数据导入新表。
- replayChanges:将OSC过程中原表的DML操作的记录应用到新表中,这些记录被保存到deltas中。
- recreateNCIndexs:重新创建辅助索引
- replayChanges:再次进行DML日志的回放操作,这些日志是在上述创建辅助索引中过程中新产生的日志。
- swapTables:将原表和新表交换名字。需要锁定两张表,不允许新数据产生。(因为改名是很快的操作,所以锁定时间很短)
Online DDL
5.6之后支持在线DDL,一下操作都可以通过在线DDL解决:
- 辅助索引的创建和删除
- 改变自增长值
- 添加或删除外键约束
- 列的重命名
具体语法内容相关,查看博客: https://www.cnblogs.com/cchust/p/4639397.html