`
liudaoru
  • 浏览: 1578638 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MySQL中ALTER TABLE时的性能问题

阅读更多

From: http://www.evget.com/zh-CN/Info/catalog/12561.html

 

  当对于一个大表进行ALTER TABLE的时候,性能问题就产生了。MySQL大部分改动的步骤如下:根据新的表结构创建一个空表,从旧表中把数据取出来插入到新表中,在删除旧表。这是个非常漫长的过程。许多人ALTER TABLE之后,都有等待1小时或者1天的痛苦经历。

  MySQL AB已经开始提升这方面的性能了。一些即将到来的特性是支持"在线"的操作,而不会去锁定表。InnoDB的开发者也在积极努力开发以排序来创建索引。MyISAM已经支持这一特性了,结果就是索引更快并且压缩了索引布局。

  并不是所有的ALTER TABLE都会使表重建。举个例子,你可以用两个方法更改或者删除列默认值(一个快,一个慢)。如果你想更改一个film的租赁期限为原来的3天到现在的5天。方法如下:

  mysql> ALTER TABLE sakila.film 
  -> MODIFY COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5;

  用SHOW  STATUS来监控这个语句,它做了1000次读和1000次插入。换句话说就是复制一个表到新表中。即使这个列的类型,大小,是否为NULL都没有改变。

  原理上来说,MySQL可以跳过创建新表。这个默认的值实际存储在.frm文件中。因此你可以更改它而没有必要接触表。MySQL也不会做优化,然而任何的MODIFY COLUMN都会导致表的重建。

  你可以使用ALTER COLUMN来修改:

  mysql> ALTER TABLE sakila.film 
  -> ALTER COLUMN rental_duration SET DEFAULT 5;

  这个语句修改了.frm文件而没有去操作表。结果就是速度非常之快。

  仅仅修改.frm文件

  我们发现修改标的.frm文件速度非常快并且当它不能那么做的时候,MySQL有的时候会重建表。如果你愿意承担一部分风险,你可以告诉MySQL做一些类型的修改而不去重建表。

  你可以不用重建表来做如下类型的操作:

  移除列的AUTO_INCREMENT属性。

  添加,移除,更改ENUM和SET。如果你移除了一个常量并且一些行包含这个值,查询语句返回这个值将会是空字符串

  基本的技术就是创建一个.frm文件并且拷贝它到以存在表的.frm文件的位置。步骤如下:

  创建一个空表,当然表布局必须是准确的。除了一些更改的项。

  执行FLUSH TABLES WITH READ LOCK.这一步将关闭使用的所有的表并且防止了这些表被打开。

  交换.frm文件。

  执行UNLOCK TABLES释放读锁。

  为了做例子,我们给skila.film表的rating列添加一个常量。当前的列如下:

  mysql> SHOW COLUMNS FROM sakila.film LIKE 'rating'; 
  +--------+------------------------------------+------+-----+---------+-------+ 
  | Field  | Type                               | Null | Key | Default | Extra | 
  +--------+------------------------------------+------+-----+---------+-------+ 
  | rating | enum('G','PG','PG-13','R','NC-17') | YES  |     | G       |       | 
  +--------+------------------------------------+------+-----+---------+-------+

  我们添加一个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-14的,而不是在中间,那样做的话就会修改现有的值了,R值变为PG-14,NC-17变为R依此类推。

  现在连交换.frm文件,操作系统命令如下

  root:/var/lib/mysql/sakila# mv film.frm film_tmp.frm 
  root:/var/lib/mysql/sakila# mv film_new.frm film.frm 
  root:/var/lib/mysql/sakila# mv film_tmp.frm film_new.frm

  在回到MySQL提示符,我们要解锁,再来看看更改的结果。

  mysql> UNLOCK TABLES; 
  mysql> SHOW COLUMNS FROM sakila.film LIKE 'rating'G 
  *************************** 1. row *************************** 
  Field: rating 
  Type: enum('G','PG','PG-13','R','NC-17','PG-14')

  最后一步要做的就是删除我们已创建的表。

  mysql> DROP TABLE sakila.film_new;

  快速的创建MyISAM索引

  高效的读取MyISAM表一般的技巧是,关闭键,读取数据,重新启用键。

  mysql> ALTER TABLE test.load_data DISABLE KEYS; 
  -- load the data 
  mysql> ALTER TABLE test.load_data ENABLE KEYS;

  这样可以工作的原因是MyISAM延迟了创建键值直到数据读取之后,重要的是,它可以有序的创建索引。结果就非床快并且无碎片和压缩的索引树。

  不过,对于唯一索引这种方法就不行了。因为DISABLE KEYS仅仅应用于非唯一的索引。MyISAM在内存中创建唯一索引并且读取每一行来校验唯一性。一旦索引大小超出了内存大小,读取会极度缓慢。

  前一部分所说的ALTER TABLE的技巧,可以加速这个过程,前提是你需要多做一点工作和承担一部分风险。这对于备份来说很有用。比如,当你发现所有的数据是无效的并且不需要做唯一性检查。

  你需要做的步骤如下:

  创建一个期望的表。但是不要有任何的索引。

  读取数据来创建MYD文件。

  创建另一个空表,这次要包含索引。这会创建.frm和.MYI文件。

  用个读锁来刷新表。

  对第二个表的.frm和.MYI进行重命名。因此MySQL会把它们当作第一个表使用。

  释放读锁。

  使用REPAIR TABLE来创建表的索引。会以排序的方式创建索引,包括了唯一索引。

  这个方法对于大表来说,速度格外的快。

分享到:
评论
2 楼 liudaoru 2010-03-22  
解决乱码问题:
set character_set_database=utf8;set names 'utf8';
1 楼 liudaoru 2010-03-15  

SELECT * FROM q100m into outfile 'test1.sql';

load data infile 'test1.sql' into table q100m_temp;

alter table q100m_temp add index i_temp (abc,def);

相关推荐

    alter table test rename test1; --修改表名alter table test add colum

    在MySQL中,`ALTER TABLE`语句是一种非常实用的工具,它允许用户修改现有表的结构,包括但不限于添加、删除或修改列、更改表名以及调整表的存储引擎等。这种灵活性极大地提高了数据库管理的效率,使得开发人员能够在...

    MySQL Alter Table 修改表信息.docx

    MySQL Alter Table 修改表信息 MySQL Alter Table 语句是一种 poderosa 语句,允许用户修改表信息,包括增加或删减字段、更改字段的数据类型和属性、创建或取消索引、修改表的评注和表的类型等。 增加字段 ALTER ...

    MySQL中的alter table命令的基本使用方法及提速优化

    mysql>alter table pet add weight int; 2. 删除列 alter table tbl_name drop col_name 例如, 删除pet表中的weight这一列 mysql>alter table pet drop weight; 3. 改变列 分为改变列的属性和改变列的名字 改变...

    alter table move相关知识研究

    源码层面,`ALTER TABLE MOVE`的具体实现依赖于数据库管理系统(如Oracle、MySQL等)的内部机制。在Oracle中,这个操作涉及到数据字典的更新、数据文件的读写以及重构建索引等复杂步骤。对于有兴趣深入理解这一过程...

    mysql alter table命令修改表结构实例

     实例一:使用ALTER TABLE命令向表中添加字段、修改字段类型以及设置主键。 首先创建一个表,SQL语句如下: mysql> CREATE TABLE myTable( -> ID SMALLINT -> ); 使用desc命令查看表结构: mysql> desc ...

    MySQL数据库中ALTER TABLE语句的用法研究.pdf

    MySQL数据库中ALTER TABLE语句的用法研究.pdf

    mysql alter table命令修改表结构实例详解

    mysql alter table语句可以修改表的基本结构,例如添加字段、删除字段、添加主键、添加索引、修改字段数据类型、对表重命名等等操作,本文章通过两个简单的实例向大家介绍mysql alter table的使用方法。  实例一:...

    mysql alter table修改表命令整理

    MYSQL ALTER TABLE命令用于修改表结构,例如添加/修改/删除字段、索引、主键等等,本文章通过实例向大家介绍MYSQL ALTER TABLE语句的使用方法,  MySQL ALTER语法如下: ALTER [IGNORE] TABLE tbl_name alter_spec...

    修改表 1、添加字段: alter table 表名add column 字段名 数据类型 位置 ; 2、删除字段: a

    在MySQL数据库管理系统中,`ALTER TABLE`语句是用于修改已存在的表结构的关键命令。本文将详细阐述如何使用`ALTER TABLE`来执行各种操作,包括添加字段、删除字段、修改字段、改变字段数据类型、更改表引擎、重命名...

    mysql alter table 修改表命令详细介绍

    MySQL的`ALTER TABLE`命令是数据库管理中不可或缺的一部分,它允许用户在不丢失已有数据的情况下,对表结构进行各种修改。本文将深入探讨`ALTER TABLE`的使用,包括添加、修改和删除字段、索引、主键等操作,并通过...

    MySQL学习笔记5:修改表(alter table)

    在MySQL数据库管理中,`ALTER TABLE`语句是用于修改已存在的表结构的关键命令。它允许用户在不丢失数据的情况下对表进行各种调整,包括修改字段名称、数据类型、添加或删除字段,以及更改字段的位置等。下面我们将...

    mysqlalter命令共5页.pdf.zip

    本资料“mysqlalter命令共5页.pdf”可能详细介绍了`ALTER`命令的各种用法,包括但不限于添加、删除、修改列,更改表名,添加或删除索引,以及调整表的存储引擎等。 1. **添加列**:使用`ALTER TABLE`可以向已存在的...

    MYSQL数据库中的现有表增加新字段(列)

    代码如下:ALTER TABLE `数据库名`.`表名` ADD COLUMN `PROCID` VARCHAR(6) DEFAULT ” AFTER `PPIDChanged`; –在MYSQL中,如果是表名,数据库名,列名,在你增加,修改,更新的时候都需要使用ESC键盘下的重音符号,...

    MySQL 添加、修改、删除表的列及约束等表的定义

    ALTER TABLE:添加,修改,删除表的列,约束等表... 修改列名MySQL: alter table bbb change nnnnn hh int; 修改列名SQLServer:exec sp_rename’t_student.name’,’nn’,’column’; 修改列名Oracle:lter table bbb

    mysql alter 操作 - 4ngel's blog

    ### MySQL ALTER操作详解 在MySQL数据库管理中,`ALTER`命令是一种非常实用且重要的工具,它允许我们在不删除...在实际应用中,根据具体的业务需求选择合适的`ALTER`操作,可以有效地提升数据库性能并简化维护工作。

Global site tag (gtag.js) - Google Analytics