加快alter table操作的速度

相关说明

Mysql 的alter table 操作的性能对大表来说是个大问题。mysql执行大部分修改表结构操作的方法是用新的结构创建一个空表,从旧表中查出所有数据插入新表,然后删除旧表。这样的操作可能需要很长时间,如果内存不足而表又很大,而且还有很多索引的情况下尤其如此。许多人都有这样的经验,alter table操作需要花费数个小时甚至数天才能完成。
一般而言,大部分alter table操作将导致mysql服务中断。对常见的场景而言我们会使用两种技巧:
1.现在一台不提供服务的机器上执行alter table操作,然后和提供服务的主库进行切换;
2.另外一种技巧是“影子拷贝”。影子拷贝的技巧是用要求的表结构创建一张和源表无关的新表,然后通过重命名和删表操作交换两张表。也有一些工具可以完成影子拷贝工作。
当然不是所有的alter table操作都会引起表重建。例如有两种方法可以改变或者删除一个劣的默认值。假如修改电影的默认租赁期限,从3天改到5天。
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操作来改变列的默认值:
alter table sakila.film
alter column rental_duration set default 5;这个语句会直接修改.frm 文件而不设计表数据。所以这个操作非常快。

快速创建myisam索引

为了高效地载入数据到myisam表中,有一个常用的技巧是先禁用索引、载入数据、然后重新启用索引:
mysql> alter table test.load_data disable keys;
–load the data
mysql>alter table test.load enable keys;
这个技巧能够发挥作用,是因为构架索引的工作呗延迟到数据完全载入之后,这个时候已经通过排序来构架索引了。这样会快很多,并且使得索引树的碎片更少、更紧凑。
不幸的是,这个办法对唯一索引无效,因为disable keys只对非唯一索引有效。
InnoDB有一个类似的技巧,这依赖于InnoDB的快速在线索引创建功能。先删除所有的非唯一索引,然后增加新的列,最后重新创建删除掉的索引。

总结

良好的schema设计原则是普遍适用的,但mysql有它自己的实现细节要注意。概括来说,尽可能保持任何东西小而简单总是好的。设计时尽量遵循简单原则:

  • 尽量避免过度设计,例如会导致极其复杂查询的schema设计,或者有多列的表设计(很多的意思是介于有点多和非常多之间)
  • 使用小而简单的合适数据类型,除非真实数据模型中有确切的需要,否则应该尽可能避免使用null值
  • 尽量使用相同的数据类型存储相似或相关的值,尤其是要在关联条件中使用的列。
  • 注意可变长字符串,其在临时表和排序时可能导致悲观的按最大长度分配内存。
  • 尽量使用整型定义标识列。
  • 避免使用mysql已经遗弃的特性,例如指定浮点数的精度,或者整数的显示宽度。
  • 小心使用enum和set。最好避免使用bit。

范式和反范式要结合使用。

猜你喜欢

转载自blog.csdn.net/qq_18377515/article/details/80959598