我有一个表,它有 170,002,225 行,大约 35 列和两个索引。我想添加一列。alter table 命令用了大约 10 个小时。在那段时间处理器似乎既不忙,也没有过多的 IO 等待。这是一个具有大量内存的 4 路高性能盒子。
这是我能做的最好的吗?有什么我可以在调整数据库时优化添加列的东西吗?
我有一个表,它有 170,002,225 行,大约 35 列和两个索引。我想添加一列。alter table 命令用了大约 10 个小时。在那段时间处理器似乎既不忙,也没有过多的 IO 等待。这是一个具有大量内存的 4 路高性能盒子。
这是我能做的最好的吗?有什么我可以在调整数据库时优化添加列的东西吗?
我过去遇到过非常相似的情况,我以这种方式提高了操作的性能:
INSERT INTO new_table (column1,..columnN) SELECT (column1,..columnN) FROM current_table;
ALTER TABLE
在 MySQL 中实际上是要创建一个具有新模式的新表,然后重新INSERT
所有数据并删除旧表。您可以通过创建新表、加载数据然后重命名表来节省一些时间。
来自“高性能 MySQL 书”(percona 家伙):
有效加载 MyISAM 表的常用技巧是禁用键,加载数据并保留键:
mysql> ALTER TABLE test.load_data DISABLE KEYS;
-- load data
mysql> ALTER TABLE test.load_data ENABLE KEYS;
好吧,我建议使用最新的 Percona MySQL 版本,因为 MySQL 手册中有以下注释
在其他情况下,MySQL 会创建一个临时表,即使不需要严格复制数据。对于 MyISAM 表,您可以通过将 myisam_sort_buffer_size 系统变量设置为较高的值来加快索引重新创建操作(这是更改过程中最慢的部分)。
您可以ALTER TABLE DISABLE KEYS
先执行,然后添加列,然后添加ALTER TABLE ENABLE KEYS
. 我看不出这里有什么可以做的。
顺便说一句,你不能去 MongoDB 吗?添加列时它不会重建任何内容。
也许您可以在更改表之前删除索引,因为大部分时间都在构建索引?
结合对其他答案的一些评论,这是对我有用的解决方案(MySQL 5.6):
create table mytablenew like mytable;
alter table mytablenew add column col4a varchar(12) not null after col4;
alter table mytablenew drop index index1, drop index index2,...drop index indexN;
insert into mytablenew (col1,col2,...colN) select col1,col2,...colN from mytable;
alter table mytablenew add index index1 (col1), add index index2 (col2),...add index indexN (colN);
rename table mytable to mytableold, mytablenew to mytable
在一个 75M 行的表上,在插入之前删除索引会导致查询在 24 分钟而不是 43 分钟内完成。
其他答案/评论有insert into mytablenew (col1) select (col1) from mytable
,但ERROR 1241 (21000): Operand should contain 1 column(s)
如果您在选择查询中有括号,则会导致结果。
其他答案/评论有insert into mytablenew select * from mytable;
,但ERROR 1136 (21S01): Column count doesn't match value count at row 1
如果您已经添加了一列,这会导致。