我试图优化我的代码插入数据到MySQL的一部分。我应该链插入,使一个巨大的多行插入或多个单独的插入更快?
当前回答
通常,由于连接开销,多个插入会更慢。一次执行多个插入将减少每次插入的开销。
根据您使用的语言,您可以在访问db并将每个插入添加到批处理之前,使用编程/脚本语言创建一个批处理。然后,您将能够使用一个连接操作执行大型批处理。这是Java中的一个例子。
其他回答
我知道我在回答这个问题几乎两年半之后才回答这个问题,但我只是想提供一些来自我现在正在从事的项目的硬数据,这些数据表明,在每个插入中执行多个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的值)。
https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html
插入一行所需的时间由以下因素决定,其中数字表示大致的比例: 连接:(3) 向服务器发送查询:(2) 解析查询:(2) 插入行:(1 ×行大小) 插入索引:(1 ×索引个数) 关闭:(1)
由此可见,发送一个大语句将为每个插入语句节省7的开销,进一步阅读文本还说:
如果同时插入来自同一客户端的多行,请使用带有多个VALUES列表的INSERT语句一次插入几行。这比使用单独的单行INSERT语句快得多(在某些情况下快很多倍)。
在同一时间通过导线发送尽可能多的插入。实际的插入速度应该是相同的,但是您将从网络开销的减少中看到性能的提高。
MYSQL 5.5 一条sql insert语句需要300到450毫秒。 而下面的stats是内联多个insert语句。
(25492 row(s) affected)
Execution Time : 00:00:03:343
Transfer Time : 00:00:00:000
Total Time : 00:00:03:343
我想说内联是一种方式:)
我会添加信息,一次太多行取决于它们的内容可能导致得到一个大于“max_allowed_packet”的包。
也许可以考虑使用类似PHP的array_chunk这样的函数对大数据集进行多次插入。