将大型 MyISAM table 转换为 InnoDB
Converting Large MyISAM table to InnoDB
我有一个 MyISAM table(1000 万行,3.5G,计划达到 ~80M),但我总是无法将其转换为 InnoDB。
我试过了:
ALTER TABLE
- 2 分钟后失去连接。也许我做错了。
mysqldump
- 尝试创建转储,然后将 ENGINE=MyISAM
更改为 ENGINE=InnoDB
。
它开始很好,但是随着新 table 中行数的增长(~3M),它变得越来越慢,最后在几个小时后超时(--reconnect
已开启) .
如果我将缓冲池大小增加到 2G,它会在更多行 (~6M) 后变慢,但机器会耗尽 RAM。
在转储恢复期间的 SHOW PROCESSLIST
中,我看到许多查询在 "query end" 状态下停留了 2-3 分钟。无法从 google-ing 理解它是什么意思。
INSERT INTO ... SELECT * FROM
- 创建了相同的结构 table 并尝试了这个。在几百万行之后也会减慢然后超时。 (感谢@Ernestas Stankevičius 提醒我这一点。)
服务器:
AWS EC2 4GB Ubuntu14.04
my.cnf
:
wait_timeout=28800
connect_timeout=28800
innodb_lock_wait_timeout=28800
net_read_timeout=7200
net_write_timeout=7200
innodb_buffer_pool_size=1G
innodb_io_capacity=100 /*200 is heavy on the machine*/
innodb_flush_log_at_trx_commit=0
reconnect=1
我的解决方案是从新的 (InnoDB) table 结构中删除一些索引,然后添加数据。
我用INSERT new_table SELECT * FROM old_table
复制数据
删除的索引越多 - 数据进入的速度越快。
之后,我重新创建了索引。
感谢@i486.
innodb_buffer_pool_size=2G
对于 4GB 的机器来说可能是危险的高。试试1500M。交换或 运行 内存不足比使用小缓存更糟糕。
运行 来自 mysql 命令行工具的 ALTER
,而不是某些 UI。 (UI 可能有您要达到的时间限制。
你 运行 MySQL 是什么版本?你有多少索引?请向我们展示 SHOW CREATE TABLE
。删除所有辅助键,只保留 PRIMARY KEY
。转换后添加其他索引; 5.6 或更高版本可以做到 "inplace".
如果您没有PRIMARY KEY
,请创建一个; InnoDB 真的需要一个。
这可能涵盖了大多数情况:
CREATE TABLE new LIKE real;
ALTER TABLE new ENGINE=InnoDB,
DROP ..., -- all the secondary keys
ADD PRIMARY (...), -- if needed
ENGINE=InnoDB;
INSERT INTO new (...)
SELECT ... FROM real ORDER BY ... -- insert in PK order
ALTER TABLE new
ADD index ...; -- rebuild secondary key(s) (see note)
RENAME TABLE real TO old, new TO real;
DROP TABLE old;
注意:如果您是 运行 5.5 或更早版本,请在单个 ALTER 中添加所有辅助键。如果您是 运行 5.6 或更高版本,请一次添加一个。
我有一个 MyISAM table(1000 万行,3.5G,计划达到 ~80M),但我总是无法将其转换为 InnoDB。
我试过了:
ALTER TABLE
- 2 分钟后失去连接。也许我做错了。mysqldump
- 尝试创建转储,然后将ENGINE=MyISAM
更改为ENGINE=InnoDB
。
它开始很好,但是随着新 table 中行数的增长(~3M),它变得越来越慢,最后在几个小时后超时(--reconnect
已开启) .
如果我将缓冲池大小增加到 2G,它会在更多行 (~6M) 后变慢,但机器会耗尽 RAM。
在转储恢复期间的 SHOW PROCESSLIST
中,我看到许多查询在 "query end" 状态下停留了 2-3 分钟。无法从 google-ing 理解它是什么意思。
INSERT INTO ... SELECT * FROM
- 创建了相同的结构 table 并尝试了这个。在几百万行之后也会减慢然后超时。 (感谢@Ernestas Stankevičius 提醒我这一点。)
服务器:
AWS EC2 4GB Ubuntu14.04
my.cnf
:
wait_timeout=28800
connect_timeout=28800
innodb_lock_wait_timeout=28800
net_read_timeout=7200
net_write_timeout=7200
innodb_buffer_pool_size=1G
innodb_io_capacity=100 /*200 is heavy on the machine*/
innodb_flush_log_at_trx_commit=0
reconnect=1
我的解决方案是从新的 (InnoDB) table 结构中删除一些索引,然后添加数据。
我用INSERT new_table SELECT * FROM old_table
复制数据
删除的索引越多 - 数据进入的速度越快。
之后,我重新创建了索引。
感谢@i486.
innodb_buffer_pool_size=2G
对于 4GB 的机器来说可能是危险的高。试试1500M。交换或 运行 内存不足比使用小缓存更糟糕。
运行 来自 mysql 命令行工具的 ALTER
,而不是某些 UI。 (UI 可能有您要达到的时间限制。
你 运行 MySQL 是什么版本?你有多少索引?请向我们展示 SHOW CREATE TABLE
。删除所有辅助键,只保留 PRIMARY KEY
。转换后添加其他索引; 5.6 或更高版本可以做到 "inplace".
如果您没有PRIMARY KEY
,请创建一个; InnoDB 真的需要一个。
这可能涵盖了大多数情况:
CREATE TABLE new LIKE real;
ALTER TABLE new ENGINE=InnoDB,
DROP ..., -- all the secondary keys
ADD PRIMARY (...), -- if needed
ENGINE=InnoDB;
INSERT INTO new (...)
SELECT ... FROM real ORDER BY ... -- insert in PK order
ALTER TABLE new
ADD index ...; -- rebuild secondary key(s) (see note)
RENAME TABLE real TO old, new TO real;
DROP TABLE old;
注意:如果您是 运行 5.5 或更早版本,请在单个 ALTER 中添加所有辅助键。如果您是 运行 5.6 或更高版本,请一次添加一个。