一. 使用批量插入,将多条单独的 insert 合并成一次操作
即:insert into table values (a1, b1, c1), (a2, b2, c2);
解析:将多条 insert 合并后,减少MySQL日志量(即MySQL的 binlog 和 innodb 的事务日志),降低日志刷盘的数据量和频率,从而提高效率。通过合并多条 insert 语句,还能减少SQL语句的解析次数,减少和数据库的交互,减少了网络传输的IO。
二. 修改批量插入缓冲区大小参数: bulk_insert_buffer_size,调大批量插入的缓存
这个参数默认为 8M,例如设置成 100M
set global bulk_insert_buffer_size = 1024*1024*100;
三. 设置 innodb_flush_log_at_trx_commit = 0
相对于 innodb_flush_log_at_trx_commit = 1, 设置为 0 可以明显的提高导入的速度。
set global innodb_flush_log_at_trx_commit=0;
解析:
0: log buffer 中的数据将以每秒一次的频率写入到 log file 中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的 commit 并不会触发任何的 log buffer 到 log file 的刷新或者从文件系统到磁盘的刷新操作。
1: 在每次事务提交的时候将 log buffer 中的数据都会写入到 log file,同时也会触发文件系统到磁盘的同步;
2: 事务提交会触发 log buffer 到 log file 的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘的同步操作。
四. 设置事务提交为 手动提交
因为 MySQL 事务默认是自动提交的(autocommit),这样每插入一条数据,都会进行一次 commit,所以通过手动提交事务,可以减少创建事务时的消耗。一般可以设置为 1000 条insert 提交一次。
【解决方案1】:
通过在 my.cnf中添加以下行。我能够做到。
innodb_autoinc_lock_mode =2
sync_binlog=1
bulk_insert_buffer_size=512M
key_buffer_size=512M
read_buffer = 50M
Max_allowed_packet=1M
Net_buffer_length=8k
和 innodb_flush_log_at_trx_commit=2,我在另一个链接中看到它说它将速度提高到 160 倍。 输出性能:超过 24 小时到 2 小时;
通常将innodb_buffer_pool_size其配置为物理内存的50%到75%
innodb_flush_log_at_trx_commit,1改为了0
2.尝试修改参数加快导入速度
在MySQL中,有一对大名鼎鼎的“双一”参数,即 innodb_flush_log_at_trx_commit 与 sync_binlog 。为了安全性这两个参数默认值为1,为了快速导入脚本,我们可以临时修改下这两个参数,下面简单介绍下这两个参数:
innodb_flush_log_at_trx_commit默认值为1,可设置为0、1、2
如果innodb_flush_log_at_trx_commit设置为0,log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行.该模式下,在事务提交的时候,不会主动触发写入磁盘的操作。 如果innodb_flush_log_at_trx_commit设置为1,每次事务提交时MySQL都会把log buffer的数据写入log file,并且flush(刷到磁盘)中去. 如果innodb_flush_log_at_trx_commit设置为2,每次事务提交时MySQL都会把log buffer的数据写入log file.但是flush(刷到磁盘)操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。
sync_binlog默认值为1,可设置为[0,N)
当sync_binlog =0,像操作系统刷其他文件的机制一样,MySQL不会同步到磁盘中去而是依赖操作系统来刷新binary log。 当sync_binlog =N (N>0) ,MySQL 在每写 N次 二进制日志binary log时,会使用fdatasync()函数将它的写二进制日志binary log同步到磁盘中去。
这两个参数可以在线修改,若想快速导入,可以按照下面步骤来操作:
# 1.进入MySQL命令行 临时修改这两个参数setglobalinnodb_flush_log_at_trx_commit = 2;setglobalsync_binlog = 2000;# 2.执行SQL脚本导入mysql -uroot -pxxxxxx testdb < testdb.sql# 3.导入完成 再把参数改回来setglobalinnodb_flush_log_at_trx_commit = 1;setglobalsync_binlog = 1;
还有另外一种场景是你的需求是新建从库,或者是不需要产生binlog,这时候导入SQL脚本时可以设置暂时不记录binlog,可以在脚本开头增加 set sql_log_bin=0; 然后再执行导入,这样速度会进一步加快。如果你的MySQL实例没有开启binlog则不需要再执行该语句了。
max_connection=1000
innodb_file_per_table=1
innodb_buffer_pool_size=1G
innodb_log_file_size=256M
innodb_log_buffer_size=256M
innodb_flush_log_at_trx_commit=2 需要放mysqlld_safe节点下。
symbolic-links=0
innodb_lru_scan_depth=256
#sync_binlog=0
#innodb_flush_log_at_trx_commit=0
wait_timeout=2880000
#interactive_time=2880000
max_allowed_packet=1G
max_connections = 1000
innodb_file_per_table=1
innodb_buffer_pool_size=10G
innodb_log_file_size=256M
innodb_log_buffer_size=256M
bulk_insert_buffer_size = 1G
innodb_flush_log_at_trx_commit=0
innodb_autoinc_lock_mode =2
sync_binlog=0
bulk_insert_buffer_size=512M
key_buffer_size=512M
#read_buffer=50M
net_buffer_length=8k
character_set_server = utf8mb4
sql_mode = NO_ENGINE_SUBSTITUTION