MySQL - 我们如何确定在表中插入大量行的批量插入语句的最佳数量?

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_pa​​cket变量,速度会增加多少。那么,问题是,如何确定批量插入的最佳步长?

Bil*_*win 5

以 mysqldump 工具的代码为例。它生成插入多行的 INSERT 语句。考虑到行的长度可以是可变的,它如何决定最佳的行数?

它逐行追加行,而包含数据行的 INSERT 语句的总长度小于net_buffer_length。这是另一个 MySQL 配置变量,它影响您可以提交到服务器的最大单个语句。

换句话说,如果 INSERT 语句的长度 + 下一行数据的长度 > net_buffer_length,则完成当前语句,然后使用下一行数据开始新语句。