我试图优化我的代码插入数据到MySQL的一部分。我应该链插入,使一个巨大的多行插入或多个单独的插入更快?
当前回答
我只是做了一个小的基准测试,似乎对于很多行它不是更快。这里是我插入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是最好的选择。
其他回答
一般来说,对数据库的调用次数越少越好(意味着更快、更高效),所以尽量以最小化数据库访问的方式编写插入代码。记住,除非使用连接池,否则每次数据库访问都必须创建一个连接,执行sql语句,然后断开连接。相当多的开销!
下面是我做的一个PHP小测试的结果:
我试图在3种不同的方式插入3000条记录,使用PHP 8.0, MySQL 8.1 (mysqli)
多个插入查询,包含多个事务:
$start = microtime(true);
for($i = 0; $i < 3000; $i++)
{
mysqli_query($res, "insert into app__debuglog VALUE (null,now(), 'msg : $i','callstack','user','debug_speed','vars')");
}
$end = microtime(true);
echo "Took " . ($end - $start) . " s\n";
完成5次,平均11.132秒(+/- 0.6秒)
多个插入查询,一个事务:
$start = microtime(true);
mysqli_begin_transaction($res, MYSQLI_TRANS_START_READ_WRITE);
for($i = 0; $i < 3000; $i++)
{
mysqli_query($res, "insert into app__debuglog VALUE (null,now(), 'msg : $i','callstack','user','debug_speed','vars')");
}
mysqli_commit($res);
$end = microtime(true);
echo "Took " . ($end - $start) . " ms\n";
5次测试的结果:0.48s (+/- 0.04s)
单个聚合插入查询
$start = microtime(true);
$values = "";
for($i = 0; $i < 3000; $i++)
{
$values .= "(null,now(), 'msg : $i','callstack','user','debug_speed','vars')";
if($i !== 2999)
$values .= ",";
}
mysqli_query($res, "insert into app__debuglog VALUES $values");
$end = microtime(true);
echo "Took " . ($end - $start) . " ms\n";
5次测试的结果:0.085s (+/- 0.05s)
因此,对于3000行插入,看起来像:
在单个写事务中使用多个查询比在每个插入中使用多个事务进行多个查询快22倍。 使用单个聚合插入语句仍然比使用单个写事务的多个查询快6倍
通常,由于连接开销,多个插入会更慢。一次执行多个插入将减少每次插入的开销。
根据您使用的语言,您可以在访问db并将每个插入添加到批处理之前,使用编程/脚本语言创建一个批处理。然后,您将能够使用一个连接操作执行大型批处理。这是Java中的一个例子。
我只是做了一个小的基准测试,似乎对于很多行它不是更快。这里是我插入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是最好的选择。
多次插入更快,但它有线程。另一个危险是禁用约束检查临时使插入快得多。你的桌子有没有它并不重要。例如,测试禁用外键,享受速度:
SET FOREIGN_KEY_CHECKS=0;
当然,你应该在插入后重新打开它:
SET FOREIGN_KEY_CHECKS=1;
这是插入大数据的常用方法。 数据完整性可能会被破坏,所以在禁用外键检查之前应该注意这一点。
推荐文章
- 在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”对等物(雄辩的)