Dav*_*rks 14 mysql innodb myisam performance
我正在通过 LOAD DATA INFILE 加载一个 100GB 的文件。我在 MyISAM 上取得了很好的成功,几个小时就完成了。
我现在正在尝试使用 InnoDB。负载以超过 10MB/秒的速度快速启动(观察表文件增长,file_per_table已打开)。
但是在大约 5GB 的数据之后它会减慢到 2-4MB/秒的范围,当我超过 20GB 时它会下降大约 2MB/秒。
InnoDB 缓冲池大小为 8G。在运行 LOAD DATA INFILE 命令之前,我已经完成了以下操作:
SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....
Run Code Online (Sandbox Code Playgroud)
我不明白为什么它开始良好并随着时间的推移放缓。
此外,使用相同的设置,我使用 InnoDB 和 MyISAM 以及 5GB 测试数据集对表运行相同的 LOAD DATA INFILE 命令,MyISAM 速度提高了 20 倍:
InnoDB:
mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886 Deleted: 0 Skipped: 0 Warnings: 6
Run Code Online (Sandbox Code Playgroud)
我的ISAM:
mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886 Deleted: 0 Skipped: 0 Warnings: 6
Run Code Online (Sandbox Code Playgroud)
还有什么我应该考虑尝试的吗?MyISAM 引擎能够更好地保持负载率。
额外细节:
我试过单独加载文件,没有区别。
顺便说一句,我有 150 个文件,每个文件 500MB,在每个文件中,键被排序。
一夜之间获得40GB,12小时后,负载率下降到0.5MB/秒,这意味着操作实际上是不可能的。
我还没有在其他论坛上找到类似问题的任何其他答案,在我看来,InnoDB 不支持将大量数据加载到大小超过几 GB 的表中。
我注意到你关机了autocommit。那将在ibdata1中堆积如此多的数据。为什么?
ibdata1 中存储了七 (7) 类信息:
ibdata1根据隔离级别,某些信息对某些事务可见。此类操作可能会产生意外的主键锁和大量幻像数据。随着这两件事的增加,您应该预期会放缓。
建议:启用自动提交
我看到你有这个:
alter table item_load disable keys;
Run Code Online (Sandbox Code Playgroud)
DISABLE KEYS 不适用于 InnoDB。原因如下:
DISABLE KEYS简单地关闭 MyISAM 表的二级索引更新。当您在禁用键的情况下将 INSERT 批量插入 MyISAM 表时,会导致快速表加载以及 PRIMARY KEY 和所有唯一索引的构建。运行时ENABLE KEYS,所有二级索引都在表上线性构建并附加到.MYD.ibdata1有一个专用于二级索引插入的结构。目前,没有规定像 MyISAM 一样处理索引。为了说明这一点,请注意我尝试在 MySQL 的 InnoDB 表上运行 DISABLE KEYS
mysql> show create table webform\G
*************************** 1. row ***************************
Table: webform
Create Table: CREATE TABLE `webform` (
`nid` int(10) unsigned NOT NULL,
`confirmation` text NOT NULL,
`confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
`redirect_url` varchar(255) DEFAULT '<confirmation>',
`status` tinyint(4) NOT NULL DEFAULT '1',
`block` tinyint(4) NOT NULL DEFAULT '0',
`teaser` tinyint(4) NOT NULL DEFAULT '0',
`allow_draft` tinyint(4) NOT NULL DEFAULT '0',
`submit_notice` tinyint(4) NOT NULL DEFAULT '1',
`submit_text` varchar(255) DEFAULT NULL,
`submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
`submit_interval` int(11) NOT NULL DEFAULT '-1',
PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------+
| Note | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select version();
+------------+
| version() |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)
mysql>
Run Code Online (Sandbox Code Playgroud)
您注意到 MyISAM 的加载速度比 InnoDB 快 20 倍。你想让它快 24-25 倍吗?然后运行以下命令:
ALTER TABLE item_load ROW_FORMAT=Fixed;
Run Code Online (Sandbox Code Playgroud)
这将在没有任何其他 DDL 更改的情况下将 INSERT 速度提高 20-25%。副作用:MyISAM 表的大小可以增长 80%-100%,甚至可能更大。
您也可以在 InnoDB 表上运行它,但是 InnoDB 的ACID 兼容行为和MVCC仍然是其性能的瓶颈,特别是如果 VARCHAR 字段显着增加被写入ibdata1.
这个问题的最终答案是不要将 InnoDB 用于大量引用表。MyISAM 的速度快得惊人,整个负载的磁盘速度接近全吞吐量,InnoDB 陷入困境。MyISAM 很简单,但在这种情况下,此表的要求也很简单。对于通过 LOAD DATA INFILE 批量加载的简单参考表,MyISAM 是要走的路,到目前为止一切顺利。
但请注意,如果您同时运行 MyISAM 和 InnoDB 表,您将需要考虑为 2 个缓存机制分配内存,每个引擎都有自己独特的缓存,需要单独的内存分配。
小智 5
您可以尝试将输入文件拆分为更小的块。
我个人 为此使用http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html。
如果在导入过程中获得表的表锁会发生什么?也许 InnoDB 的行级锁定会减慢它的速度(MyISAM 使用表锁)。
你也可以在这里阅读更多的想法:http : //derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql