mysql alter table 原理_MySQL之高性能alter table操作

文章浏览阅读1.2k次。一、alter table 原理MySQL的alter table操作的性能对大表来说,是一个大问题,为什么呢?我们来看看alter table的底层原理

一、alter table 原理

MySQL的alter table操作的性能对大表来说,是一个大问题,为什么呢?

我们来看看alter table的底层原理,大多数情况下(有的时候未必会重建表),当我们执行一个alter table操作后,其底层会执行如下几个操作:

用一个新的结构创建一个空表;

从旧表中查出所有数据插入新表;

然后删除旧表。

当数据表特别大的时候,这样的操作严重影响了效率,因此,在实际开发中,我们应该避免这样的耗时操作,采用高效的操作。

对于常见的场景,我们能使用的一般有两种方法:

一种是先在一台不提供服务的机器上执行alter table操作,然后和提供服务的主库进行切换;

另一种技巧是影子拷贝;

影子拷贝:用要求的表结构创捷一张和源表无关的表,然后通过重命名和删表操作交换两张表。

影子拷贝举例:

mysql> create table new_table like old_table; #创建一张和原表一样结构的表

mysql> rename table old_table to tem_table,new_table to old_table; #重命名表名

mysql> drop table if exists tem_tablel; #删除旧表

但是我们考虑这样一种情况,如果我们只是简单的该表某一列的默认值等情况,那么我们也要赋值整个表的话,那是不是很繁琐?如以下代码语句(修改默认值为5):

mysql> alter table table1

-> modify column col1 tinyint(3) not null default 5;

这条语句会拷贝整个表到一个新表,但是就是做一个修改默认值的操作,其他都没有改变。

理论上,我们应该跳过建表的和复制操作,直接修改字段属性即可,这样将会大大加快了整个执行效率。

二、修改.frm文件

我们知道,表的结构是存储在.frm文件中,如果我们能直接修改这个文件,而不必该表表本身,然而,在MySQL中,所有的modify column都会导致表重建。

但是alter column 命令却可以修改.frm文件,因此,如上的sql语句可以改写为如下:

mysql> alter table table1

-> alter column col1 tinyint(3) not null default 5;

这个语句直接修改.frm文件,不涉及表数据,所以,操作非常快。

三、扩展.frm文件的操作

注意:对.frm的操作是比较危险的操作,建议操作前,先对原.frm文件做一个备份。虽然快速,但是危险不推荐。

为了实现高性能的sql,很多时候,我们就是简单的改变表结构的一些信息,不需要对整个表的大量数据进行操作,因此,我们可以以.frm文件作为切入点,直接操作。

基本的技术是为想要的表结构创建一个新的.frm文件,然后用它替换掉已经存在的那张表的.frm文件,主要步骤如下:

创建一张有相同结构的空表,并进行修改(例如增加enum常量);

执行 flush with read lock;命令。(关闭所有正在使用的表,并禁止任何表被打开)

交换.frm文件;

执行unlock tables;命令。(释放第二步的读锁)

3.1 举例分析

下面以给sakila. film表的rating 列增加一一个常量为例来说明。当前列看起来如下::

d801c6f5cb0d04564698c7957d03d3df.png

假设我们需要增加一个PG-14的分级:

mysql> CREATE TABLE sakila.film new LIKE sakila.film;

mysql> ALTER TABLE sakila.film_new

-> MODIFY COLUMN rating ENUM('G','PG','PG-13','R' ,'NC-17', 'PG-14')

-> DEFAULT 'G' ;

mysql> FLUSH TABLES WITH READ LOCK;

注意,我们是在常量列表的末尾增加一个新的值。如果把新增的值放在中间,例如PG-13之后,则会导致已经存在的数据的含义被改变:已经存在的R值将变成PG-14,而已经存在的NC-17将成为R,等等。接下来用操作系统的命令交换.frm文件:

/var/lib/mysq1/sakila# mv film.frm film_tmp.frm

/var/lib/mysql/sakila# mv film_new.frm film.frm

/var/lib/mysql/sakila# mv film_tmp.frm film_new.frm

再回到MySQL命令行,现在可以解锁表并且看到变更后的效果了:

mysql> UNLOCK TABLES;

mysql> SHOW COLUMNS FROM sakila. film LIKE rating'G

e52293f4142a2c242ed94ade0a475b1e.png

最后需要做的是删除为完成这个操作而创建的辅助表:

mysql> DROP TABLE sakila.film_new;

原创文章,作者:筱凯,如若转载,请注明出处:https://www.jingyueyun.com/ask/613.html

(0)
筱凯筱凯
上一篇 2024 年 7 月 13 日
下一篇 2024 年 7 月 13 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

云产品限时秒杀。精选云产品高防服务器,500M大带宽限量抢购  >>点击进入