我试图优化我的代码插入数据到MySQL的一部分。我应该链插入,使一个巨大的多行插入或多个单独的插入更快?
当前回答
当涉及到插入时,Mysql和MariaDB的优化是多么糟糕,这是荒谬的。 我测试了mysql 5.7和mariadb 10.3,没有真正的区别。
我已经在一台带有NVME磁盘、70000 IOPS、1.1 GB/sec seq吞吐量的服务器上进行了测试,这可能是全双工(读和写)。 该服务器也是高性能服务器。 给了它20gb的内存。 数据库完全为空。
在做多行插入时,我收到的速度是每秒5000个插入(尝试了1MB到10MB的数据块)
现在是线索: 如果我添加另一个线程并插入到相同的表中,我突然有2x5000 /秒。 再多一个线程,我就有15000个线程了
考虑一下:当执行一个线程插入时,这意味着您可以按顺序写入磁盘(索引除外)。 当使用线程时,你实际上降低了可能的性能,因为它现在需要做更多的随机访问。 但事实证明,mysql的优化非常糟糕,线程的帮助很大。
这种服务器的实际性能可能是每秒数百万,CPU空闲,磁盘空闲。 原因很明显,mariadb和mysql一样有内部延迟。
其他回答
一般来说,对数据库的调用次数越少越好(意味着更快、更高效),所以尽量以最小化数据库访问的方式编写插入代码。记住,除非使用连接池,否则每次数据库访问都必须创建一个连接,执行sql语句,然后断开连接。相当多的开销!
多次插入更快,但它有线程。另一个危险是禁用约束检查临时使插入快得多。你的桌子有没有它并不重要。例如,测试禁用外键,享受速度:
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语句快得多(在某些情况下快很多倍)。
推荐文章
- 如何从命令行在windows中找到mysql数据目录
- 如何找到MySQL的根密码
- 如何改变字符集(和排序)在整个数据库?
- mySQL:: insert到表,数据从另一个表?
- 重复键忽略?
- 将表从一个数据库复制到另一个数据库的最简单方法?
- 如何通过查询在MySQL中获得数据库结构?
- 插入一行到熊猫数据框架
- MySQL删除表中的所有行,并将ID重置为零
- 在准备语句中使用“like”通配符
- MySQL中的表名是否区分大小写?
- 库未加载:libmysqlclient.16。在OS X 10.6上使用mysql2 gem运行'rails server'时出现dylib错误
- 如何知道MySQL表最近一次更新?
- 在MySQL中的一个查询中更新多个具有不同值的行
- 如果表存在则删除表并创建它,如果不存在则创建它