如何提高Perl / DBI脚本的性能,该脚本从一个数据库服务器中选择100万行并将其插入另一个数据库服务器?

时间:2012-07-06 19:16:42

标签: mysql perl dbi

我使用的是最新版本的MySQL(工作台),Perl和DBI。

我在唯一的服务器上有两个唯一的数据库。我在Server1上的DB1上查询table1,加载到一个数组中,然后用while将所述表插入到Server2上的DB2上的table2中。

这不是直接复制,因为我实际上正在对表1进行选择。

我正在尝试加快脚本速度,或者在必要时更改查询。

我正在使用绑定并将准备语句移出循环,这确实有帮助。但是,我最终仍然会拨打160万次调用来插入table2 / db2 / server2,这会占用大量时间(每次调用3100秒或大约2-3毫秒)。

有两个subs& insert2tempData在while循环中用于加载我的DB2 table2。它被称为160万次AND query_dev_load_local_dbs,用于查询DB1然后调用第二个子。

为了简单起见,我在循环中留下了这个准备,但在我的代码中,这不在while循环中,而是在调用此子的sub中。

sub insert2tempData {
    $query4tmpData = $Locdbh_NetCool->prepare ("INSERT INTO kpincpolldata.kpitempData
        (monitoredObjectId, monitoredInstId, pollTime, tdwTime, errorCode, value)
        VALUES(?, ?, ?, ?, ?, ?)");

    $query4tmpData->execute($row[0], $row[1], $row[2], $row[3], $row[4],
                            $row[5]);
    warn "Problem in retrieving results", $query4tmpData->errstr(), "\n"
        if $query4tmpData->err();

} #End sun insert to tempData

这是用于查询server1,DB1和table1的主要子对象。它调用while循环

sub query_dev_load_local_dbs {
    $queryRemote = $Devdbh_NetCool->prepare("SELECT * FROM ncpolldata.pollData
                                   WHERE pollTime >= $STARTU AND pollTime < $ENDU
                                   AND monitoredObjectId = 1");

    $queryRemote->execute();

    while (@row = $queryRemote->fetchrow_array()) {

        #** Call to sub insert2tempData**
        &insert2tempData($Locdbh_NetCool);

        warn &print2log ("Problem in retrieving results"), $queryRemote->errstr(), "\n"
            if $queryRemote->err();
    } # End while

} # End sub query_dev_load_local_dbs

2 个答案:

答案 0 :(得分:4)

您在上面发布的代码完全有可能与您感知的性能问题无关。在您正在使用的数据库服务器上插入那么多行可能需要很长时间。以下是我要看的内容:

  1. 关闭AutoCommit,启用。

    每次insert提交时,Server2会对{{1}}产生严重的性能影响,具体取决于其配置方式。将整个流程批量处理为一个事务完全有可能加快速度。但这实际上取决于服务器的配置方式,索引的构建方式等等。

    这将我们带到:

  2. 有能力的DBA可以提供帮助。

    检查管理MySQL服务器的是谁,看看它们是否可以帮助您排除故障。谁知道,他们甚至可能拥有能够帮助您解决问题的DBA工具,而不会在代码中执行任何不同的操作甚至允许您完全废弃此脚本。

    除非你是DBA:

  3. 您可能会在Stack Exchange site寻找DBA。

  4. 在您发布的代码中可能需要修复一些小问题,但如果数据库是瓶颈,则无关紧要。找到瓶颈!

答案 1 :(得分:3)

我使用fetchrow_arrayref()而不是fetchrow_array(),因为这样每次获取行时都不必复制所有返回值。这应该可以加快速度。您也可以查看bind_columns

然后我对while循环和prepare的意思并不完全清楚,所以无论如何我都这样说:将$query4tmpData=$Locdbh_NetCool->prepare移出子地并移到其他地方它可以prepare d一次,然后在sub中重用它。你可能有这个。


还有一些事情:

  • 您应始终use strictuse warnings。我在你的潜艇中没有看到my。请使用那些pragma。它们让您的生活更轻松。
  • 当您无法INSERT读取“检索结果时出现问题”时发出的警告。如果它发生,那可能会让你感到困惑。
相关问题