Wes*_*Wes 2 mysql optimization bulkinsert
我正在创建虚拟 MySQL 表数据用于测试目的。表的最小大小为 400 万行。
来自 MySQL文档-
如果要同时从同一客户端插入多行,请使用具有多个 VALUES 列表的 INSERT 语句一次插入多行。这比使用单独的单行 INSERT 语句要快得多(在某些情况下快很多倍)。
我有一个 Java 程序,可以生成一个 sql 脚本来执行批量插入。它的调用方式如下-
java CreateData -rows 4000000 -stepSize 10000 > testdata.sql
where
rows = total number of rows to insert in the database
stepSize = size of each bulk insert statement.
Thus if we have 4 million rows and a stepSize of 10000,
then we have 400 bulk insert statements.
Run Code Online (Sandbox Code Playgroud)
我尝试对 400 万行进行一次批量插入,但正如预期的那样,出现了错误 -
$ time mysql -uroot < testdata.sql
ERROR 2006 (HY000) at line 2: MySQL server has gone away
Run Code Online (Sandbox Code Playgroud)
所以我尝试通过稳步增加步长进行实验,当我最终得到错误时 -
ERROR 1153 (08S01) at line 1150017: Got a packet bigger
than 'max_allowed_packet' bytes
Run Code Online (Sandbox Code Playgroud)
在那之前,随着步长的增加,我观察到执行的总时间略有减少。一些样本值 -
stepSize 2000
real 3m37.564s
user 0m7.608s
sys 0m0.180s
stepSize 24000
real 1m48.399s
user 0m4.788s
sys 0m0.168s
stepSize 32000
real 1m49.490s
user 0m4.544s
sys 0m0.072s
stepSize 160000
real 1m43.927s
user 0m3.800s
sys 0m0.108s
stepSize 220000
real 1m33.025s
user 0m3.772s
sys 0m0.120s
stepSize 230000
ERROR 1153 (08S01) at line 1150017:
Got a packet bigger than 'max_allowed_packet' bytes
Run Code Online (Sandbox Code Playgroud)
我不知道如果增加max_allowed_packet变量,速度会增加多少。那么,问题是,如何确定批量插入的最佳步长?
以 mysqldump 工具的代码为例。它生成插入多行的 INSERT 语句。考虑到行的长度可以是可变的,它如何决定最佳的行数?
它逐行追加行,而包含数据行的 INSERT 语句的总长度小于net_buffer_length
。这是另一个 MySQL 配置变量,它影响您可以提交到服务器的最大单个语句。
换句话说,如果 INSERT 语句的长度 + 下一行数据的长度 > net_buffer_length,则完成当前语句,然后使用下一行数据开始新语句。