繁体   English   中英

尽可能快地插入多行

[英]Multiple row inserts as fast as possible

我已经看到多个线程对此进行了讨论,但是答案总是有完全不同的结论。 尤其是我想知道是否真的有必要创建一个自己的准备好的语句(使用适当数量的占位符)以将其作为单个查询插入。 我希望当我在for循环之前和之后使用beginTransactionendTransaction ,pdo / php等待事务直到收集所有数据为止,并且一旦服务器命中endTransaction行,它将以单个查询的形式发送这些数据。

为了达到最佳性能,我需要如何用多个插入来重写这样的for循环插入(通常具有1至300行,但也可能达到2000行)。

for($i=0; $i<$baseCount; $i++)
    {
        $thLevel = $bases[$i]["ThLevel"];
        $gold = $bases[$i]["Gold"];
        $elixir = $bases[$i]["Elixir"];
        $darkElixir = $bases[$i]["DarkElixir"];
        $dateFound = $elixir = $bases[$i]["TimeFound"];

        $query = $db->prepare("INSERT INTO bot_attacks_searchresults (attack_id, available_gold, available_elixir, available_dark_elixir, date_found, opponent_townhall_level)
        VALUES (:attack_id, :available_gold, :available_elixir, :available_dark_elixir, :date_found, :opponent_townhall_level)");
        $query->bindValue(':attack_id', $attackId);
        $query->bindValue(':available_gold', $gold);
        $query->bindValue(':available_elixir', $elixir);
        $query->bindValue(':available_dark_elixir', $darkElixir);
        $query->bindValue(':date_found', $dateFound);
        $query->bindValue(':opponent_townhall_level', $thLevel);
        $query->execute();
    }
  • 准备一次声明。 MySQL对它进行了一次词法分析,因此对查询的任何后续调用都将很快,因为它已经被词法化了,并且juts需要参数。

  • 在循环之前启动事务。 这样做是为了使您的硬盘驱动器可以在一个输入输出操作中记下所有行。 默认模式是1个插入查询= 1个硬盘的I / O。

  • 创建循环,在此处绑定参数并调用$query->execute();

  • 退出循环并commit()事务。

完整代码:

$db->beginTransaction();

$query = $db->prepare("INSERT INTO bot_attacks_searchresults (attack_id, available_gold, available_elixir, available_dark_elixir, date_found, opponent_townhall_level)
        VALUES (:attack_id, :available_gold, :available_elixir, :available_dark_elixir, :date_found, :opponent_townhall_level)");

for($i = 0; $i < $baseCount; $i++)
{
    $thLevel = $bases[$i]["ThLevel"];
    $gold = $bases[$i]["Gold"];
    $elixir = $bases[$i]["Elixir"];
    $darkElixir = $bases[$i]["DarkElixir"];
    $dateFound = $elixir = $bases[$i]["TimeFound"];

    $query->bindValue(':attack_id', $attackId);
    $query->bindValue(':available_gold', $gold);
    $query->bindValue(':available_elixir', $elixir);
    $query->bindValue(':available_dark_elixir', $darkElixir);
    $query->bindValue(':date_found', $dateFound);
    $query->bindValue(':opponent_townhall_level', $thLevel);
    $query->execute();
}

$db->commit();

这是一个非常粗糙的概念证明:

<?php

$values = array();

for($i=0;$i<10;$i++)
{
$values[] = "($i)";
}

$values = implode($values,',');

$query = "INSERT INTO my_table VALUES $values";

echo $query;

?>

输出INSERT INTO my_table VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)

您需要对其稍作重组,以使用prepare(PHP不是我的强项),但是原理是相同的。 即,您在循环内构建查询,但仅执行一次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM