Answers:
https://dev.mysql.com/doc/refman/8.0/zh-CN/insert-optimization.html
插入行所需的时间由以下因素决定,其中数字表示近似比例:
- 连接:(3)
- 向服务器发送查询:(2)
- 解析查询:(2)
- 插入行:(1×行大小)
- 插入索引:(1×索引数)
- 闭幕:(1)
由此可见,发送一条大语句将为您节省每个插入语句7的开销,在进一步阅读本文时还说:
如果要同时从同一客户端插入许多行,请使用具有多个VALUES列表的INSERT语句一次插入几行。这比使用单独的单行INSERT语句要快得多(某些情况下要快很多倍)。
我知道我在回答这个问题之前有人问近两年半年后,但我只是想现在该节目确实做得每个刀片有多个值块是提供从项目我工作的一些硬数据MUCH比顺序的单个VALUE块INSERT语句快。
我在C#中为此基准编写的代码使用ODBC将数据从MSSQL数据源(〜19,000行,在开始任何写入之前已读取所有数据)读取到内存中,并将MySql .NET连接器(Mysql.Data。*)填充到通过准备好的语句将数据从内存插入MySQL服务器上的表中。它的编写方式使我可以动态地调整每个准备好的INSERT的VALUE块的数量(即,一次插入n行,在运行之前我可以在其中调整n的值。)我还运行了测试每个n多次。
执行单个VALUE块(例如,一次1行)需要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个写入捆绑在一起,也可以显着提高速度(运行时减少了n倍),直到达到n = 5到n = 10之间的某个位置为止,在这一点上,改善明显下降,而在n = 10到n = 50的范围内,改进几乎可以忽略不计。
希望可以帮助人们决定(a)是否使用多重准备的想法,以及(b)每个语句要创建多少VALUE块(假设您要使用可能足够大以使查询超过最大查询大小的数据的工作)对于MySQL,我相信很多地方默认是16MB,根据服务器上设置的max_allowed_packet值,它可能更大或更小。)
一个主要因素将是您是否正在使用事务引擎以及是否自动提交。
默认情况下,自动提交功能是打开的,您可能希望将其保持打开状态。因此,您所做的每个插入都会执行自己的事务。这意味着,如果每行插入一次,则将为每一行提交一个事务。
假设有一个线程,则意味着服务器需要将每行的某些数据同步到磁盘。它需要等待数据到达持久存储位置(希望是RAID控制器中由电池供电的RAM)。这本质上是相当缓慢的,并且在这些情况下可能会成为限制因素。
我当然假设您使用的是事务引擎(通常是innodb),并且您没有进行设置以降低持久性。
我还假设您正在使用单个线程来进行这些插入。使用多个线程会使事情有些混乱,因为某些版本的MySQL在innodb中具有工作组提交功能-这意味着执行自己的提交的多个线程可以共享一次写入事务日志的操作,这很好,因为这意味着与持久性存储的同步次数更少。
另一方面,结果是您真的想使用多行插入。
它会适得其反,但在大多数情况下,至少有10,000行。因此,如果将它们最多批量处理1000行,则可能很安全。
如果您使用的是MyISAM,那么还有很多其他事情,但是我不会让您感到厌倦。和平。
荒谬的是,在插入时如何优化Mysql和MariaDB。我测试了mysql 5.7和mariadb 10.3,两者之间没有真正的区别。
我已经在具有NVME磁盘,70,000 IOPS,1.1 GB /秒seq吞吐量的服务器上进行了测试,并且这可能是全双工(读和写)。
该服务器也是高性能服务器。
给它20 GB的内存。
数据库完全为空。
进行多行插入时,我收到的速度为每秒5000次插入(使用1MB到10MB的数据块进行尝试)
现在的提示:
如果我添加另一个线程并将其插入到SAME表中,我突然会得到2x5000 / sec。还有一个线程,我总共有15000个/秒
请考虑以下问题:在执行一个线程插入时,这意味着您可以顺序写入磁盘(索引例外)。使用线程时,实际上会降低可能的性能,因为它现在需要进行更多的随机访问。但是现实检查表明,mysql的优化非常差,线程可以提供很多帮助。
此类服务器的实际性能可能约为每秒数百万,CPU处于空闲状态,磁盘处于空闲状态。
原因很清楚,就像MySQL具有内部延迟一样,mariadb也是如此。
id
,parent_id
)VALUES(1,NULL)。下一组值之一链接到该行。如果拆分成多个块,并且该集合进入另一个块,则可能会在第一个块之前对其进行处理,从而使整个过程失败。知道如何处理吗?
多次插入速度更快,但应该加快。另一个麻烦是禁用临时检查插入约束,快得多。表格是否有没有关系。例如,测试禁用外键并享受速度:
SET FOREIGN_KEY_CHECKS=0;
当然,您应该在插入后通过以下方式将其重新打开:
SET FOREIGN_KEY_CHECKS=1;
这是插入大量数据的常用方法。数据完整性可能会中断,因此在禁用外键检查之前,您应该注意这一点。