在MySQL数据库中大幅加速1000万行插入

时间:2014-04-12 14:22:28

标签: php mysql insert innodb

$files = glob('dataset/*.xml');

foreach ($files as $key => $txc) {
    $txcDoc = new DOMDocument();
    $txcDoc->load($txc);

    $operators = $txcDoc->getElementsByTagName("Operators");
    foreach ($operators as $operatorTag) {
        foreach ($operatorTag->getElementsByTagName("Operator") as $operator) {
            $reference = $operator->getAttribute("id");
            @$nationalOperatorCode = $operator->getElementsByTagName("NationalOperatorCode")->item(0)->nodeValue;
            $operatorCode = $operator->getElementsByTagName("OperatorCode")->item(0)->nodeValue;
            $operatorShortName = $operator->getElementsByTagName("OperatorShortName")->item(0)->nodeValue;
            @$operatorNameOnLicense = $operator->getElementsByTagName("OperatorNameOnLicense")->item(0)->nodeValue;
            @$tradingName = $operator->getElementsByTagName("TradingName")->item(0)->nodeValue;

            $operatorSQL = "INSERT IGNORE INTO `operator` (`reference`, `national_operator_code`, `operator_code`, `operator_short_name`, `operator_name_on_license`, `trading_name`) VALUES (:reference, :nationalOperatorCode, :operatorCode, :operatorShortName, :operatorNameOnLicense, :tradingName);";

            $operatorStmt = $conn->prepare($operatorSQL);
            $operatorStmt->execute(array(':reference' => $reference, ':nationalOperatorCode' => $nationalOperatorCode, ':operatorCode' => $operatorCode, ':operatorShortName' => $operatorShortName, ':operatorNameOnLicense' => $operatorNameOnLicense, ':tradingName' => $tradingName));
        }
    }
}

上面的PHP循环遍历78,654个XML文件(1.2gb),解析其数据,然后将数据插入MySQL数据库。上面的代码段只是文件的十分之一,但是,还有另外10-15 foreach个结构,就像foreach ($operators一样。 (要查看整个文件,请单击here

我的问题是插入250个文件的数据需要10-20分钟。我需要大幅提高速度,以便将所有数据插入< 1-2个小时。

数据库引擎是MySQL,表格都是InnoDB。我怎样才能加速这些插入?

2 个答案:

答案 0 :(得分:2)

显然有很多事情要看,你并没有提供太多细节......

然而,容易加速这种质量插入的一件事通常是:

  1. 删除在插入数据的表格上定义的所有索引

  2. 插入数据

  3. 重新创建

  4. 之前定义的所有索引

    这种速度加快的原因是索引必须重新组织并且只能一次而不是每次插入操作。我经常感到惊讶的是,有多大差异......

    如果另外你真的想调整你的php实现,那么在示例运行中使用分析器来理解确切花费的时间是有意义的。专注于那些非常突出的部分。但请记住,将无尽的时间投入到完美主义中是没有意义的。让CPU工作比浪费时间便宜得多: - )

答案 1 :(得分:2)

我认为您不必调用$ conn-> prepare($ operatorSQL);在每个循环中,您可以在循环之外准备语句并在循环内执行它。我不知道你实际上会获得多少性能提升,但是当你拥有数百万行时,以这种方式重构它是有意义的。

此外,已知@运算符(又名静音运算符)会降低PHP脚本的速度。

也许代码本身很好,但如果你使用的是远程sql server,那么很可能是带宽问题。

你可能会考虑根本不使用php - 例如,Java可以更快地解析大量数据。使用Java时,您可以创建多线程程序,同时可以同时解析多个文件。

最后但并非最不重要 - 您可以升级硬件。读取数千个文件对于磁盘I / O来说会很重要。使用SSD而不是HDD可以加快速度。

与其他人提到的一样,您应该对代码进行基准测试。 Xdebug是众所周知的php工具,它可以生成profiling个信息。根据分析信息,您可以在代码中找到bottlenecks,当您确实知道问题出在哪里时,可以考虑之前提到的可能性。