我试图优化我的代码插入数据到MySQL的一部分。我应该链插入,使一个巨大的多行插入或多个单独的插入更快?
当前回答
一般来说,对数据库的调用次数越少越好(意味着更快、更高效),所以尽量以最小化数据库访问的方式编写插入代码。记住,除非使用连接池,否则每次数据库访问都必须创建一个连接,执行sql语句,然后断开连接。相当多的开销!
其他回答
一个主要因素是您是否使用事务引擎以及是否开启了自动提交。
自动提交是默认开启的,你可能想让它保持开启状态;因此,您执行的每个插入操作都会执行自己的事务。这意味着如果您对每行执行一次插入,那么您将为每行提交一个事务。
假设只有一个线程,这意味着服务器需要为每一行同步一些数据到磁盘。它需要等待数据到达一个持久存储位置(最好是RAID控制器中有电池支持的ram)。这本身就相当缓慢,可能会成为这些情况下的限制因素。
当然,我假设你正在使用事务性引擎(通常是innodb),并且你没有调整设置来降低持久性。
我还假设您使用单个线程来进行这些插入。使用多线程会让事情变得有点混乱,因为一些版本的MySQL在innodb中有工作组提交功能——这意味着多个线程可以共享一次写入事务日志的操作,这很好,因为这意味着更少的同步到持久存储。
另一方面,结果是,您确实希望使用多行插入。
它会产生反效果,但在大多数情况下至少是10,000行。因此,如果将它们批量处理到1,000行,则可能是安全的。
如果你在使用MyISAM,还有很多其他的东西,但我不会用这些来烦你。和平。
多次插入更快,但它有线程。另一个危险是禁用约束检查临时使插入快得多。你的桌子有没有它并不重要。例如,测试禁用外键,享受速度:
SET FOREIGN_KEY_CHECKS=0;
当然,你应该在插入后重新打开它:
SET FOREIGN_KEY_CHECKS=1;
这是插入大数据的常用方法。 数据完整性可能会被破坏,所以在禁用外键检查之前应该注意这一点。
我会添加信息,一次太多行取决于它们的内容可能导致得到一个大于“max_allowed_packet”的包。
也许可以考虑使用类似PHP的array_chunk这样的函数对大数据集进行多次插入。
我只是做了一个小的基准测试,似乎对于很多行它不是更快。这里是我插入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是最好的选择。
https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html
插入一行所需的时间由以下因素决定,其中数字表示大致的比例: 连接:(3) 向服务器发送查询:(2) 解析查询:(2) 插入行:(1 ×行大小) 插入索引:(1 ×索引个数) 关闭:(1)
由此可见,发送一个大语句将为每个插入语句节省7的开销,进一步阅读文本还说:
如果同时插入来自同一客户端的多行,请使用带有多个VALUES列表的INSERT语句一次插入几行。这比使用单独的单行INSERT语句快得多(在某些情况下快很多倍)。
推荐文章
- 在Python中插入列表的第一个位置
- 如何停止mysqld
- 检查MySQL表是否存在而不使用“select from”语法?
- 从NOW() -1天选择记录
- 从表中选择1是什么意思?
- 数据库性能调优有哪些资源?
- 如何更改表的默认排序规则?
- MySQL foreign_key_checks是否影响整个数据库?
- 设置NOW()为datetime数据类型的默认值?
- 在MySQL中Datetime等于或大于今天
- 删除MySQL中的主键
- 我如何在MySQL中添加更多的成员到我的enum类型列?
- 相当于varchar(max)在MySQL?
- PHP与MySQL 8.0+错误:服务器请求身份验证方法未知的客户端
- laravel5“LIKE”对等物(雄辩的)