MySQL进阶知识

1. InnoDB快速索引建立数据库

InnoDB快速索引建立,即在表中已经存在大量数据的状况下,可以快速建立和删除辅助索引的能力。服务器


1.1 背景并发

对于老版本的MySQL,在InnoDB表中已经存在数据的状况下,对其添加或删除索引的过程十分缓慢,那时create index和drop index语句的工做方式为:性能

① 建立一个空的且带有目标索引结构的新表;spa

② 逐行拷贝数据行到新表,插入新行的同时更新索引;排序

③ 所有拷贝完后,删除旧表,并将新表重命名为旧表名字;索引


1.2 版本要求事务

从MySQL 5.5开始,为InnoDB表建立和删除辅助索引再也不须要复制整个表的内容,从而使得操做速度大为提高。内存


1.3 适用范围table

快速索引建立的性能加速适用于辅助索引,不适用于主键索引。InnoDB表中的数据行存储在基于主键组织的聚簇索引中,造成某些数据库系统称为的“索引组织表”。由于表结构与主键紧密相关,所以重定义主键索引老是须要复制表中的数据。


1.3 方法技巧

这种新机制一般也意味着,你可使用以下方法加速索引表的建立和加载:先建立只有聚簇索引的表,而后加载数据,最后再添加辅助索引


1.4 语法

InnoDB快速索引建立的语法仍旧是create index, drop index, alter table


◇ alter table

你能够在一条alter table语句中为一个表同时建立多个索引,并且因为只须要扫描一次聚簇索引,因此这种作法的效率也更高。例如:

alter table tbl_name add index (B), add unique index (C);

若是在alter table语句以前已经有大量的数据行被插入到表中,那么先插入数据后添加辅助索引将比先添加辅助索引后加载数据要快得多


◇ crate index

你也能够一次建立一个索引,但此时每条create index语句都须要扫描一次聚簇索引,所以效率上不如上面的alter table,例如:

create index B on tbl_name (B);

create unique index C on tbl_name (C);


◇ drop index

删除InnoDB表的辅助索引一样也不须要复制表中的数据,你能够在一条alter table语句中同时删除多个索引,或者使用多个drop index语句。例如:

alter table tbl_name drop index B, drop index C;

或者

drop index B on tbl_name;

drop index C on tbl_name;


1.5 实现细节

☆ InnoDB有两种类型的索引:聚簇索引和辅助索引。由于聚簇索引把数据值存储在B-tree节点里面,因此添加或删除聚簇索引老是会引起数据复制,并建立表的新副本。同时由于每一个辅助索引都包含了主键值的副本,因此当你修改主键时,所有辅助索引都须要从新建立;

☆ 删除辅助索引很简单。服务器只须要更新内部的InnoDB系统表和MySQL数据字典表,以反映索引再也不存在的事实便可。同时InnoDB会把该索引占用的空间返还给索引所在的表空间,以便新索引或其它表的数据行可使用;

☆ 添加辅助索引时,InnoDB会对表进行扫描,并使用内存缓冲区和临时文件按辅助索引列的列值对数据行进行排序。而后B-tree就以键值序被建立,这比以随机顺序把行插入索引更有效。因为B树节点被填满后自动分裂,因此以这种方式构建索引会致使索引具备更高的填充因子,从而使后续访问更高效;


1.6 并发问题

☆ 建立辅助索引

① 建立或删除InnoDB辅助索引时,表被锁定在共享模式下。此时,任何写操做都将被阻塞,但读操做不受影响;

② 建立InnoDB辅助索引的create index和alter table语句开始执行后,对该表能够查询,但不能更新;


☆ 修改聚簇索引

① 更改表的聚簇索引时,因为必须复制数据,因此表将以独占模式被锁定。所以,在建立新的聚簇索引期间,表上的全部操做都将被阻塞;

② 修改InnoDB聚簇索引的alter table语句开始执行后,全部的查询也必须等待,直到操做完成;

③ 修改主键的alter table语句开始执行后,任何事务都不能够访问该表,由于在聚簇索引重构期间老表已经被删除


☆ 语句执行

① 对于InnoDB表,create index和alter table语句老是会等待当前正在访问表的事物提交或回滚;

② 重定义InnoDB主键的alter table操做会等待当前正在访问该表的全部select语句执行完,或是等待其所在的事物提交;


☆ 内容 

新建立的辅助索引只包括create index和alter table语句开始执行时表中已提交的数据,而不包括未提交数据、老版本数据(MVCC)和已标记为删除但还未删除的数据


1.7 重建聚簇索引的过程

MySQL建立新的聚簇索引的过程为:建立一个具备目标索引结构的临时表,而后从原表向临时表复制数据。一旦数据复制完成,原表被重命名为一个其它的临时名字,而临时表被赋予原表的名字,最后一步是从数据库删除原表。


重建InnoDB聚簇索引须要将数据拷贝到一个全新的聚簇索引。请注意,全部的InnoDB表都以聚簇索引形式存储。


1.8 崩溃恢复

在alter table语句执行期间,若是服务器崩溃,没有数据会丢失。可是聚簇索引和辅助索引的崩溃恢复过程是不一样的:

① 若是在建立InnoDB辅助索引时服务器崩溃,则在恢复时,MySQL将删除任何部分建立的索引。你必须从新运行alter table或create index语句;

② InnoDB聚簇索引的崩溃恢复较为复杂,请联系MySQL支持;


1.9 局限性

① 同时包含了drop index和add index,且二者指定的是同一个索引的alter table语句,使用的是表复制,而不是快速索引建立;

② 临时表的索引建立使用的是表复制,而不是快速索引建立;

③ 为避免InnoDB数据字典和MySQL数据字典之间的一致性问题,当使用alter table ... change语法重命名列时,使用的是表复制而不是快速索引建立;

④ MySQL 5.5不支持高效地建立或删除外键约束。所以,若是使用alter table添加或删除references约束,子表将被复制,而不是使用快速索引建立;

⑤ InnoDB表的optimize table被自动映射为alter table操做,以重建表、更新索引统计信息,并释放聚簇索引中未使用的空间。此操做没法使用快速索引建立。同时,辅助索引也没法被高效地建立,由于辅助索引的键是根据它们在主键中出现的顺序插入的。