哪个更快:多个单个INSERT或一个多行INSERT?

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

http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

插入行所需的时间由以下因素确定,其中数字表示大致的比例:

  • 连接:(3)
  • 发送查询到服务器:(2)
  • parsing查询:(2)
  • 插入行:(1×行的大小)
  • 插入索引:(1×索引号)
  • 闭幕:(1)

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

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

我知道我在回答这个问题差不多两年半了,但是我只是想提供一些我正在处理的项目的一些硬数据,这些数据表明确实每插入多个VALUE块的数量是很多的比顺序的单个VALUE块INSERT语句更快。

我在C#中为这个基准testing编写的代码使用ODBC从MSSQL数据源(大约19,000行,在开始任何写入之前读取所有数据)和MySql .NET连接器(Mysql.Data。*)通过预先准备好的语句将内存中的数据插入MySQL服务器的表中。 它的写法是允许我dynamic调整每个准备好的INSERT的VALUE块的数量(例如,一次插入n行,我可以在运行之前调整n的值)。我也运行了testing每个n多次。

做单个VALUE块(例如,一次一行)花费5.7-5.9秒运行。 其他值如下:

每次2排: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个写在一起提供了一个戏剧性的改善速度(运行时间减less了n倍),直到你到达n = 5和n = 10之间的某个地方,此时的改善明显下降,在n = 10到n = 50的范围内,改进可以忽略不计。

希望能够帮助人们决定(a)是否使用multiprepare思想,以及(b)为每个语句创build多less个VALUE块(假设您要处理的数据可能足够大,以便将查询推送到最大查询大小对于MySQL,我相信在很多地方默认情况下是16MB,根据服务器上设置的max_allowed_pa​​cket的值可能更大或更小。)

一个主要的因素是你是否使用事务引擎,是否有自动提交。

Autocommit在默认情况下是打开的,你可能想把它打开; 因此,您所做的每个插入都执行自己的事务。 这意味着如果你每行插入一行,你将会为每一行提交一个事务。

假设一个线程,这意味着服务器需要同步一些数据光盘的每一行。 它需要等待数据到达一个持久的存储位置(希望RAID控制器中的电池备份RAM)。 这本质上相当缓慢,并可能成为这些情况下的限制因素。

我当然假设你使用的是事务引擎(通常是innodb),而且你还没有调整设置来降低持久性。

我还假设你正在使用一个线程来做这些插入。 使用multithreading有点混乱,因为某些版本的MySQL在innodb中有工作组提交 – 这意味着多个执行自己的提交的线程可以共享一个写入事务日志,这是很好的,因为这意味着更less的同步到持久存储。

另一方面,结果是,你真的想要使用多行插入。

有一个限制,它会起反作用,但在大多数情况下,至less有10,000行。 所以,如果你把它们分成1000行,你可能是安全的。

如果你使用的是MyISAM,还有一些其他的东西,但是我不会让你感到厌烦。 和平。

尽可能多地在电线上发送尽可能多的插入物。 实际的插入速度应该是相同的,但是您会看到networking开销减less后的性能提升。

一般来说,对数据库调用的次数越less越好(意味着更快,更有效),所以尝试以最小化数据库访问的方式对插入进行编码。 请记住,除非使用连接池,否则每个数据库访问必须创build连接,执行sql,然后拆除连接。 相当多的开销!

你可能想要 :

  • 检查自动提交是否closures
  • 打开连接
  • 在一个事务中发送多批次的插入(大小约为4000-10000行,你会看到)
  • closures连接

取决于你的服务器的扩展性(与PostgreSQlOracleMSSQL ),使用multithreading和多连接执行上面的操作。

MYSQL 5.5一个sql插入语句花费了〜300到〜450ms。 而下面的统计信息是用于内嵌多个插入的统计信息。

 (25492 row(s) affected) Execution Time : 00:00:03:343 Transfer Time : 00:00:00:000 Total Time : 00:00:03:343 

我会说内联是走的方式:)

通常,由于连接开销,多个插入将会变慢。 一次执行多个插入操作可以降低每个插入开销的成本。

根据你使用的是哪一种语言,你可以在编程/脚本语言中创build一个batch file,然后到db中添加每个插入文件。 然后,您将能够使用一个连接操作执行大批量操作。 这里是 Java中的一个例子。

禁用约束检查使插入速度快得多。 不pipe你的桌子有没有。 例如testing禁用外键,并享受速度:

 SET FOREIGN_KEY_CHECKS=0;