简体   繁体   English

将大型MyISAM表转换为InnoDB

[英]Converting Large MyISAM table to InnoDB

I have a MyISAM table (10M rows, 3.5G, planning to reach ~80M) and I always fail converting it to InnoDB. 我有一个MyISAM表(10M行,3.5G,计划达到~80M),我总是无法将其转换为InnoDB。

I tried : 我试过了 :

  • ALTER TABLE - It loses connection after 2 minutes. ALTER TABLE - 2分钟后失去连接。 Maybe I'm doing it wrong. 也许我做错了。

  • mysqldump - Tried creating a dump and then change the ENGINE=MyISAM to ENGINE=InnoDB . mysqldump - 尝试创建转储,然后将ENGINE=MyISAM更改为ENGINE=InnoDB

It starts well but as the number of rows in the new table grows (~3M), It becomes slower and slower and finally after some hours it times out ( --reconnect is ON). 它开始很好但随着新表中行数的增加(~3M),它变得越来越慢,最后几小时后它超时( --reconnect为ON)。

If I increase the buffer pool size to 2G it slows after more rows (~6M) but the machine runs out of RAM. 如果我将缓冲池大小增加到2G,它会在更多行(~6M)之后减慢,但机器会耗尽RAM。

In SHOW PROCESSLIST during the dump restore I see that many queries stuck for 2-3 minutes on "query end" state. 在转储恢复期间的SHOW PROCESSLIST中,我看到许多查询在“查询结束”状态下停留了2-3分钟。 Can't understand from google-ing what does it mean. 从google-ing无法理解是什么意思。

  • INSERT INTO ... SELECT * FROM - Created the same-structure table and tried this. INSERT INTO ... SELECT * FROM - 创建了相同结构的表并尝试了这一点。 Also slows down after some millions of rows and then times out. 在数百万行之后也会减速然后超时。 (Thanks @Ernestas Stankevičius for reminding me this.) (感谢@ErnestasStankevičius提醒我这个。)

The server: 服务器:

Aws EC2 4GB Ubuntu14.04 Aws EC2 4GB Ubuntu14.04

my.cnf : 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_buffer_pool_size=2G is probably dangerously high for a 4GB machine. 对于4GB的机器, innodb_buffer_pool_size=2G可能是危险的。 Try 1500M. 试试1500M。 Swapping or running out of memory is worse than having a small cache. 交换或耗尽内存比使用小缓存更糟糕。

Run the ALTER from the mysql commandline tool, not some UI. 从mysql命令行工具运行ALTER ,而不是某些UI。 (The UI probably has the time limit you are hitting. (UI可能有你要打的时间限制。

What version of MySQL are you running? 你在运行什么版本的MySQL? How many indexes do you have? 你有多少指数? Please show us SHOW CREATE TABLE . 请告诉我们SHOW CREATE TABLE Drop all secondary keys, keep only the PRIMARY KEY . 删除所有辅助密钥,仅保留PRIMARY KEY Add the other indexes after the conversion; 转换后添加其他索引; 5.6 or latter can do that "inplace". 5.6或后者可以做到“就地”。

If you have no PRIMARY KEY , create one; 如果您没有PRIMARY KEY ,请创建一个; InnoDB really needs one. InnoDB确实需要一个。

This probably covers most cases: 这可能涵盖大多数情况:

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;

Note: If you are running 5.5 or older, add all the secondary keys in a single ALTER. 注意:如果您运行的是5.5或更早版本,请在一个ALTER中添加所有辅助密钥。 If you are running 5.6 or newer, add them one at a time. 如果您运行的是5.6或更高版本,请一次添加一个。

My solution was to remove some indexes from the new (InnoDB) table structure and then add the data. 我的解决方案是从新的(InnoDB)表结构中删除一些索引,然后添加数据。
I used INSERT new_table SELECT * FROM old_table to copy the data 我使用INSERT new_table SELECT * FROM old_table来复制数据

The more indexes you remove - the faster the data gets in. 删除的索引越多 - 数据进入的速度就越快。

After that, I re-created the indexes. 之后,我重新创建了索引。
Thanks to @i486. 感谢@ i486。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM