我试图优化我的代码插入数据到MySQL的一部分。我应该链插入,使一个巨大的多行插入或多个单独的插入更快?


当前回答

我会添加信息,一次太多行取决于它们的内容可能导致得到一个大于“max_allowed_packet”的包。

也许可以考虑使用类似PHP的array_chunk这样的函数对大数据集进行多次插入。

其他回答

https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html

插入一行所需的时间由以下因素决定,其中数字表示大致的比例: 连接:(3) 向服务器发送查询:(2) 解析查询:(2) 插入行:(1 ×行大小) 插入索引:(1 ×索引个数) 关闭:(1)

由此可见,发送一个大语句将为每个插入语句节省7的开销,进一步阅读文本还说:

如果同时插入来自同一客户端的多行,请使用带有多个VALUES列表的INSERT语句一次插入几行。这比使用单独的单行INSERT语句快得多(在某些情况下快很多倍)。

一般来说,对数据库的调用次数越少越好(意味着更快、更高效),所以尽量以最小化数据库访问的方式编写插入代码。记住,除非使用连接池,否则每次数据库访问都必须创建一个连接,执行sql语句,然后断开连接。相当多的开销!

我只是做了一个小的基准测试,似乎对于很多行它不是更快。这里是我插入28000行的结果:

比10000:164.96秒 到5000分37秒 到1000时:12.56秒 到600秒:12.59秒 比500:13.81秒 到250秒:17.96秒 到400时:14.75秒 差100分27秒

看来1000 * 1000是最好的选择。

我会添加信息,一次太多行取决于它们的内容可能导致得到一个大于“max_allowed_packet”的包。

也许可以考虑使用类似PHP的array_chunk这样的函数对大数据集进行多次插入。

我知道我在回答这个问题几乎两年半之后才回答这个问题,但我只是想提供一些来自我现在正在从事的项目的硬数据,这些数据表明,在每个插入中执行多个VALUE块确实比连续的单个VALUE块insert语句快得多。

The code I wrote for this benchmark in C# uses ODBC to read data into memory from an MSSQL data source (~19,000 rows, all are read before any writing commences), and the MySql .NET connector (Mysql.Data.*) stuff to INSERT the data from memory into a table on a MySQL server via prepared statements. It was written in such a way as to allow me to dynamically adjust the number of VALUE blocks per prepared INSERT (ie, insert n rows at a time, where I could adjust the value of n before a run.) I also ran the test multiple times for each n.

做单个VALUE块(例如,一次一行)需要5.7 - 5.9秒的时间。其他取值如下:

一次两行:3.5 - 3.5秒 一次排5行:2.2 - 2.2秒 一次10行:1.7 - 1.7秒 一次50行:1.17 - 1.18秒 一次100行:1.1 - 1.4秒 一次500行:1.1 - 1.2秒 一次1000行:1.17 - 1.17秒

所以,是的,即使只是将2或3个写入捆绑在一起,也可以显著提高速度(运行时减少了n倍),直到达到n = 5和n = 10之间的某个位置,此时改进显著下降,而在n = 10到n = 50范围内的某个位置,改进几乎可以忽略不计。

希望这有助于人们决定(a)是否使用multiprepare思想,(b)每个语句创建多少VALUE块(假设你想要处理的数据可能足够大,以推动查询超过MySQL的最大查询大小,我相信在很多地方默认是16MB,可能更大或更小,这取决于服务器上设置的max_allowed_packet的值)。