索引的添加MySQL经历了一下几个历程:
一 .在MySQL 5.5版本之前,添加索引具体是这样的:
1.首先创建一张临时表和原表数据结构相同,将你要添加的索引加上。
2.把原表数据导入临时表。
3.删除原表。
4.将临时表重命名为原表。
这样做有很大问题:
首先对于大数据量的导入需要很长的时间,那么在这段时间里新增或修改的数据没办法处理。
其次如果碰上大事务正在新增或更新更新这张原表还会锁表,你还没办法用sql去导入到临时表中。
二 .但在InnoDB 1.0版本开始,支持一种Fast Index(快速索引创建)的方式,简称FIC,他是这样做的:
对于辅助索引的创建,他不需要建临时表,他会直接将原表加S锁,这样就不会有数据导入的问题。
但还是会有些其他问题:
这意味着这加索引的这段时间里这张表只能读,不能增删改。而且不适用主键索引。
三. 针对一,二阶段的问题,Facebook总结并实现了一种在线执行方案-OSC:
1.初始化,检查原表所有的问题,包括主键,触发器,外键等。
2.创建临时表,添加索引字段。
3.创建deltas表,为下一步创建触发器做准备。
4.对原表创建增删改的触发器,触发器产生的草所记录写入到上一步创建的deltas表。
5.开始OSC操作的事务。
6.删除所有辅助索引,再将原表数据通过分片文件写入临时表。
7.将deltas表中产生的记录应用到临时表中。
8.重新创建辅助索引。
10.将原表和临时表交换名字,在这个过程中会锁表,但这个过程很快。
以上便是整个OSC过程,看起来就很复杂,实际的脚本也很复杂,光是核心PHP代码就2000多行,而且有一定局限性,对于分布式无法主从同步。
四.MySQL5.6版本开始支持在线创建--Online DDL,只需一行代码:
以下是对辅助索引的添加:
ALTER TABLE table_name ADD INDEX indea_name ,ALGORITHM=INPLACE,LOCK=NONE;
ALGORITHM指定创建或删除索引得算法,有以下几类:
COPY:按照5.1之前的版本,创建临时表的方式。
INPLACE:不需要创建临时表。
DEFAULT:表示根据参数old_alter_table来判断是用COPY还是INPLACE,默认OFF,表示采用INPLACE方式。
LOCK表示加锁情况:
NONE:不添加任何锁,允许并发。
SHARE:加S锁。
EXCLUSIVE:加X锁,读写都不允许。
DEFAULT:会先判断是否可用NONE,若不能再判断是否可用SHARE模式,最后判断EXCLUSIVE。
Online DDL的原理是则好样的:
1.在创建或删除索引的同时,会将这段时间发生的增删改操作的日志写入一个缓存中,待完成索引后再重新将日志应用到表上,达到数据一致性。这个缓存的小由innodb_online_alter_log_max_size控制,默认128MB。可以根据情况调整。
需要注意的是,在这个过程中,sql不会用到正在创建的索引。