导读:在MySQL5.6之前版本,Innodb表的许多DDL操作是非常昂贵。许多ALTER TABLE操作的原理是通过创建新的空表,定义被要求的表选项和索引,然后逐行拷贝已存在记录到新表,在插入行时更新索引。在旧表所有行被拷贝完,旧表被删除和那新表被重命名为旧的表名。MySQL5.5,和MySQL5.1 有了InnoDB Plugin,优化了CREATE INDEX和DROP INDEX 避免表的拷贝行为。这个特性被称为Fast index Creation。MySQL 5.6 加强ALTER TABLE操作许多方式来避免拷贝表。另外加强的允许SELECT查询和INSERTUPDATE,和DELETE(DML)语句被处理当该表正被修改时。这些功能的组合现在被称为online DDL

语法解读:online DDL操作允许alter table 语句指定ALGORITHM,LOCK 子句。

ALGORITHM=inplace,表示DDL操作在原表上就地操作,ALGORITHM=copy ,表示采用以前方式(复制表)进行DDL 操作。DDL没有指定ALGORITHM子句,MySQL会自动选择每种DDL所允许的ALGORITHM子句(并不是所有DDL在所有情况下都支持每种ALGORITHM,如果两种都支持,默认ALGORITHM=inplace优先选择,如果指定某种DDL在某种情况下不允许的ALGORITHM,该执行的DDL 以失败告终)。

LOCK={default|none|shared|exclusive|}是显式指定alter table 的锁级别,default 表是使用所有DDL在不同情况下的默认的锁级别(也是DDL在不同情况下支持最低级别的锁)。LOCK=none不加锁,允许DML,查询并发(注意LOCK=none不是真正表示执行DDL操作不进行锁,在DDL执行真正执行时,还是加排他锁)。LOCK=SHARED不允许DML并发,允许查询。LOCK=exclusive 不允许 DML并发和查询。(alter table 没有显式指定锁的级别,默认情况使用该DDL允许的默认的最低级别锁<也就是看情况>,如果显式指定的锁是该DDL不允许的级别,该DDL以失败中止)

online DDL工作机制:通过ALGORITHM实现DDL操作是复制表还是在原表就地操作,让DDL尽量影响那些需要改变的数据,而不要操作那些不需改变的数据如:对一列设置默认值,仅对该表.frm修改而涉及数据文件。通过LOCK 实现DML,查询的并发。不管锁是哪种级别,在DDL语句正在准备时和在DDL提交时都是以独占方式访问表。而LOCK不同的级别控制是否允许在online DDL操作之前已发起的DML和查询但没有提交和回滚的事务并发。

DDL的影响范围:有些DDL操作仅影响逻辑文件(对一列设置默认值,仅对该表.frm修改不是数据文件。),有些DDL操作影响整个数据文件(重建主键,需要对整个数据进行新的聚集组织),有些DDL操作影响部分数据文件(新增二级索引,二级索引只有主键的值,只需对主键的值进行重构)。

online DDL执行时间:从上面的分析,我可以知道online DDL的执行时间的长短取决多个方面:

1:online DDL 操作的影响范围的大小。

2:online DDL 操作对象的数据量的大小。

3:online DDL 操作时,当前是否已存在需长时间执行的事务

4:online DDL 操作选取ALGORITHM(inplace不一定比copy快)和LOCK的方式

以上因素要综合考虑,才能使online DDL 操作更顺利和更高效。

OnLine DDL后innodb的索引

5.0和更早版本的MySQL中,在一个已经有很多数据的表上添加或者删除一个索引将非常耗时。CREATE INDEX和DROP INDEX通过创建一个新的空的带有要创建索引的表,然后拷贝存在的行到新表中,同时更新索引,当此时key没有排序时插入条目极慢。在所有的行都被拷贝完成以后,旧表被删除,新表被改名。

一条ALTER TABLE命令创建多个索引是可能的。这相对有效,因为聚簇索引只需要被扫描一次。比如

CREATE TABLE T1(A INT PRIMARY KEY, B INT, C CHAR(1)) ENGINE=InnoDB;

INSERT INTO T1 VALUES

(1,2,'a'), (2,3,'b'), (3,2,'c'), (4,3,'d'), (5,2,'e');

COMMIT;

ALTER TABLE T1 ADD INDEX (B), ADD UNIQUE INDEX (C);

上面的命令将创建表T1,在列A上创建聚簇的主键索引,插入几行,然后在列B和C上创建2个新的索引。如果在ALTER TABLE命令之前有很多行,这个方法将比预先创建带有全部索引的表然后加载数据有效。

你也可以一次只创建一个索引,但是每次聚簇索引都会针对CREATE INDEX扫描一次。在InnoDB中删除索引并不要求表数据的任何拷贝,因此一次删多条或者一次删一条是等价的。

重建InnoDB中的聚簇索引总是要求拷贝表中的数据。比如,如果你创建一个表时没有主键,InnoDB将为你选择一个,它可能是第一个UNIQUE key或者NOT NULL的列,或者一个系统产生的key。如果你在后来定义了一个PRIMARY KEY,数据将不得不拷贝。

2.3 实现

InnoDB有2种类型的索引:聚簇索引和二类索引,由于聚簇索引包含数据值于Btree节点之中,添加或者删除一个聚簇索引涉及到数据的拷贝,并将创建一个新的表的拷贝。一个二类索引实际上只包含索引的key和主键的值,这种类型的索引可以在不用拷贝聚簇索引中数据的情况下创建或者删除。进一步,因为二类索引包含着主键的值,当你改变主键定义的时候,将重新创建聚簇索引,所有的二级索引也将重新创建。

删除一个二类索引是简单的,只有内部的InnoDB系统表和MySQL的数据字典表需要被更新来反应索引不再存在的事实。InnoDB将返回索引所使用的空间给表空间,因此新索引或者额外表的行可以使用这些空间。

要添加一个二类索引到存在的表中,InnoDB扫描表,使用内存Buffer和临时文件按照被索引的列的顺序对行进行排序。然后Btree就被建立起来了,这比以随机顺序插入行时保证key的值有序要有效。 因为Btree节点在满了以后会分裂,按照此种方式构建的索引有一个较高的填充因子,对随后的访问具有较好的效率。

2.4 并发的考虑

测试表明对于主键的修改操作,仅rename阶段会短暂的排它锁。

mysql> drop index `PRIMARY` on t1;
Query OK, 300028 rows affected (14.76 sec)
Records: 300028 Duplicates: 0 Warnings: 0

mysql> show profile for query 43;
+----------------------+-----------+
| Status | Duration |
+----------------------+-----------+
| starting | 0.000080 |
| checking permissions | 0.000012 |
| init | 0.000004 |
| Opening tables | 0.000230 |
| setup | 0.000036 |
| creating table | 0.049951 |
| After create | 0.000301 |
| System lock | 0.282387 |
| copy to tmp table | 14.089265 |
| rename result table | 0.332012 |
| end | 0.000036 |
| query end | 0.000012 |
| closing tables | 0.000090 |
| freeing items | 0.003100 |
| cleaning up | 0.000061 |
+----------------------+-----------+
15 rows in set, 1 warning (0.00 sec)

mysql> select * from t1 limit 10;
...
mysql> show profile for query 28;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000081 |
| checking permissions | 0.000013 |
| Opening tables | 0.000022 |
| Waiting for table metadata loc | 0.254933 |
| Opening tables | 0.001558 |
| init | 0.000070 |
| System lock | 0.000026 |
| optimizing | 0.000013 |
| statistics | 0.000040 |
| preparing | 0.000035 |
| executing | 0.000008 |
| Sending data | 0.000173 |
| end | 0.000014 |
| query end | 0.000032 |
| closing tables | 0.000032 |
| freeing items | 0.000384 |
| cleaning up | 0.000036 |
+--------------------------------+----------+
17 rows in set, 1 warning (0.00 sec)

右边session2中前面在drop index之后执行了很多条查询,都没有阻塞,仅在session中的rename阶段短暂阻塞。

由于Online DDL原因,DML操作也与上面类似,不会长阻塞。但是如果例如drop primay key等操作没有使用online ddl特性,依然要copy to tmp table,那么依然会像myisam一样对DML阻塞。

对于myisam表创建index时<copy to tmp table>,select只有rename时段堵塞,DML被全程阻塞。

InnoDB online DDL与快速索引创建的更多相关文章

  1. (转)Mysql技术内幕InnoDB存储引擎-表&索引算法和锁

    表 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC% ...

  2. MySQL技术内幕InnoDB存储引擎(表&索引算法和锁)

    表 4.1.innodb存储引擎表类型 innodb表类似oracle的IOT表(索引聚集表-indexorganized table),在innodb表中每张表都会有一个主键,如果在创建表时没有显示 ...

  3. MySQL InnoDB存储引擎体系架构 —— 索引高级

    转载地址:https://mp.weixin.qq.com/s/HNnzAgUtBoDhhJpsA0fjKQ 世界上只两件东西能震撼人们的心灵:一件是我们心中崇高的道德标准:另一件是我们头顶上灿烂的星 ...

  4. mysql 优化实例之索引创建

    mysql 优化实例之索引创建 优化前: pt-query-degist分析结果: # Query 23: 0.00 QPS, 0.00x concurrency, ID 0x78761E301CC7 ...

  5. substr函数索引创建测试

    技术群里小伙伴,沟通说一条经常查询的SQL缓慢,单表SQL一个列作为条件,列是int数值类型,索引类型默认创建. 一.SQL文本substr函数索引创建测试 ,) nm1 ')需求,将上述SQL执行速 ...

  6. Database基础(二):MySQL索引创建与删除、 MySQL存储引擎的配置

    一.MySQL索引创建与删除 目标: 本案例要求熟悉MySQL索引的类型及操作方法,主要练习以下任务: 普通索引.唯一索引.主键索引的创建/删除 自增主键索引的创建/删除 建立员工表yg.工资表gz, ...

  7. mysql索引创建和使用细节

    最近困扰自己很久的膝盖积液手术终于做完,在家养伤,逛技术博客看到easyswoole开发组成员仙士可博客有关mysql索引方面的知识,自己打算重温下. 正常业务起步数据表数据量较少,不用考虑使用索引, ...

  8. 数据页结构 .InnoDb行格式、以及索引底层原理分析

    局部性原理 局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中. 首先要明白局部性原理能解决的是什么问题,也就是主存容量远远比缓存大, CP ...

  9. mysql InnoDB引擎是否支持hash索引

    看一下mysql官方文档:https://dev.mysql.com/doc/refman/5.7/en/create-index.html , 从上面的图中可以得知,mysql 是支持hash索引的 ...

随机推荐

  1. Java 面试总结(一) —— 面试常问的关键字总结

    关键字: final finalize finally throws和throw static关键字的作用 abstract 和 interface super 和 this synchronize ...

  2. createjs 小游戏开发实战

    [转载请注明出处] 紧接着上一篇文章createjs入门:http://www.cnblogs.com/beidan/p/7055422.html 这里来一篇小游戏实战篇. 游戏整体思路实现 1. 实 ...

  3. Lniux下安装mysql----编译版

    ####安装mysql-5.7.10rpm -e --nodeps mysqlrpm -e mysqlclient10useradd -g mysql -s /sbin/nologininstall_ ...

  4. 历年NOIP中的搜索题

    什么题目都不会做于是开始做搜索题. 然而我搜索题也不会做了. 铁定没戏的蒟蒻. 1.NOIP2004 虫食算 “对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立.输入数据 ...

  5. javascript事件轮询

    JavaScript 运行机制详解:再谈Event Loop 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么Ja ...

  6. Linux查看内存占用情况

    输入:top PID 进程的ID USER 进程所有者 PR 进程的优先级别,越小越优先被执行 Ninice 值 VIRT 进程占用的虚拟内存 RES 进程占用的物理内存 SHR 进程使用的共享内存 ...

  7. 关于MUI集成微信分享遇到的坑

    今天聊一下MUI这个框架吧! 首先,用这个框架也有很长一段时间了,项目不同,涉及到的功能也有不同,之前没有涉及到微信分享相关的内容!今天,遇到了,也解决了,分享出来. 下面是手顺: 1.分享的代码是参 ...

  8. (转)Maven项目标准目录结构

    场景:工作中的项目都是使用Maven的目录结构,虽然能够如期的完成开发工作,但是对于一个Maven工程的配置却并不熟悉,这里主要介绍下Maven工程的而目录结构. 1 标准目录结构 src -main ...

  9. PHP中通过sqlsrv调用存储过程——成绩排名去除重复字段的数据行

    培训考试项目中,需要实现考试成绩排名:排名参考项为分数(score降序).参加日期(attendtime升序).第几次参加考试(frequency升序):并且,每个用户只保留一条数据(pid). 考试 ...

  10. 使用pdfbox分页保存pdf为图片

    一.背景 pdfbox作为Apache开源的PDF操作工具,允许创建新的PDF文档,操作现有文档,以及从文档中提取内容的能力.Apache PDFBox还包括一些命令行实用工具.本文楼主主要介绍其中的 ...