我目前正致力于创建一个测试应用性能的环境;我正在使用MySQL和InnoDB进行测试,以找出哪些可以为我们提供最佳服务。在此环境中,我们将自动准备数据库(加载现有转储)并检测我们的测试工具。
我准备用MySQL和InnoDB测试相同的数据转储,但我已经无法将初始导入带到InnoDB部分的可用速度。最初的转储需要更长时间,但这并不关心我:
$ for i in testdb_myisam testdb_innodb; do time mysqldump --extended-insert $i > $i.sql; done
real 0m38.152s
user 0m8.381s
sys 0m2.612s
real 1m16.665s
user 0m6.600s
sys 0m2.552s
但是,导入时间差异很大:
$ for i in testdb_myisam testdb_innodb; do time mysql $i < $i.sql; done
real 2m52.821s
user 0m10.505s
sys 0m1.252s
real 87m36.586s
user 0m10.637s
sys 0m1.208s
经过研究后,我来到了Changing tables from MyISAM to InnoDB make the system slow,然后使用了set global innodb_flush_log_at_trx_commit=2
:
$ time mysql testdb_innodb < testdb_innodb.sql
real 64m8.348s
user 0m10.533s
sys 0m1.152s
恕我直言仍然令人震惊。我还为这些测试禁用了log_bin
,这里列出了all mysql variables。
我是否要接受这么长的InnoDB时间,还是可以改进它们?我完全可以控制这个MySQL服务器,因为它纯粹是为了这个测试环境。
我可以仅为初始导入应用特殊配置,并将其更改回应用程序测试,以便更好地匹配生产环境。
更新
鉴于反馈,我已禁用自动提交和各种检查:
$ time ( echo "SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0;" \
; cat testdb_innodb.sql ; echo "COMMIT;" ) | mysql testdb_innodb;date
real 47m59.019s
user 0m10.665s
sys 0m2.896s
速度提高了,但没有那么多。我的测试有缺陷吗?
更新2:
我能够获得访问不同机器的进口只花了大约8分钟。我比较了配置并将以下设置应用于我的MySQL安装:
innodb_additional_mem_pool_size = 20971520
innodb_buffer_pool_size = 536870912
innodb_file_per_table
innodb_log_buffer_size = 8388608
join_buffer_size = 67104768
max_allowed_packet = 5241856
max_binlog_size = 1073741824
max_heap_table_size = 41943040
query_cache_limit = 10485760
query_cache_size = 157286400
read_buffer_size = 20967424
sort_buffer_size = 67108856
table_cache = 256
thread_cache_size = 128
thread_stack = 327680
tmp_table_size = 41943040
通过这些设置,我现在已经下降到大约25分钟。距离MyISAM的几分钟还有一段距离,但它对我来说更有用。
答案 0 :(得分:126)
您是否尝试过InnoDB Performance Tuning Tips(特别是第一个)中的 批量数据加载提示 :
IMO,整章都值得一读。
将数据导入
InnoDB
时,请确保MySQL没有 启用自动提交模式,因为 每次需要一次日志刷新到磁盘 插入。在期间禁用自动提交 你的导入操作,环绕它 使用SET autocommit
和COMMIT
语句:SET autocommit=0; ... SQL import statements ... COMMIT;
如果使用mysqldump选项
--opt
,则会获得转储文件 快速导入InnoDB
表, 即使没有包裹他们SET autocommit
和COMMIT
语句。如果您对辅助密钥有
UNIQUE
个限制,则可以加快表格速度 通过暂时关闭进口 导入期间的唯一性检查 会话:SET unique_checks=0; ... SQL import statements ... SET unique_checks=1;
对于大表,这可以节省大量磁盘I / O,因为
InnoDB
可以使用 它的插入缓冲区写入辅助 批量索引记录。肯定 数据不包含重复 密钥。如果表中有
FOREIGN KEY
个约束,则可以 通过转动加速表进口 外键检查 导入会话的持续时间:SET foreign_key_checks=0; ... SQL import statements ... SET foreign_key_checks=1;
对于大表,这可以节省大量磁盘I / O.
答案 1 :(得分:5)
您是否尝试在一开始就开始交易并在最后提交交易?从question you linked:“修改插入数据步骤以在开始时启动事务并在结束时提交它。您将得到改进,我保证。”
请记住,InnoDB是事务性的,而MyISAM则不是。如果您没有明确控制事务,则事务引擎会将每个语句视为单个事务。这可能是昂贵的。
答案 2 :(得分:2)
我发现硬盘成为瓶颈 - 老式磁盘毫无希望,SSD还可以,但仍然远非完美。导入到tmpfs并复制数据的速度更快,详情请参阅:https://dba.stackexchange.com/a/89367/56667
答案 3 :(得分:1)
我在进行大量批量导入时遇到了问题,并推荐了已接受的答案。我发现你还可以通过以下方式加快速度:
innodb_log_file_size
* innodb_log_files_in_group
是否足以避免以亚秒级频率写入磁盘关于#2,在现代系统上,默认值为5M * 2是不够的。有关详细信息,请参阅innodb_log_file_size
和innodb_log_files_in_group