3

我需要每天将一个非常大(数百万行)的表从一个 DB2 数据库复制到另一个数据库,并且我需要使用 perl 和 DBI。

有没有比从第一个 DB 中简单地 fetchrow_array 每一行并将它们一个接一个插入到第二个 DB 更快的方法?这是我得到的:

$sth1 = $udb1 -> prepare($read_query);
$sth1 -> execute();
$sth1 -> bind_columns(\(@row{@{$sth1 -> {NAME_1c}}}));

$sth2 = $udb2 -> prepare($write_query);

while ($sth1 -> fetchrow_arrayref) {
    $sth2 -> execute($row{field_name_1}, $row{field_name_2});
}

我从一个类似的线程中实现了一些解决方案,但它仍然很慢。当然必须有更好的方法?

4

4 回答 4

5

如果将其包装到一个事务中,它应该工作得更快。使用这样的东西:

$sth1 = $udb1->prepare($read_query);
$sth1->execute();
$sth1->bind_columns(\(@row{@{$sth1->{NAME_1c}}}));

$udb2->begin_work();
$sth2 = $udb2->prepare($write_query);
while ($sth1->fetchrow_arrayref()) {
    $sth2->execute($row{field_name_1}, $row{field_name_2});
}
$udb2->commit();

如果您有数百万行,您可能希望每几千行执行一次提交。

现在,它更快的原因:

在您的情况下,每个插入都是一个自动提交的事务。换句话说,服务器必须等到您的更改真正刷新到数百万行中的每一行 - 非常慢!

当您将其包装到事务中时,服务器可以一次将数千行刷新到磁盘 - 效率更高,速度更快。

(如果您一遍又一遍地复制完全相同的表,那么通过某种唯一键来同步更改会更明智——应该快一百万倍)。

于 2013-01-08T07:22:18.990 回答
1

除了 mvp 在这里所说的之外,还有来自 DBI 文档的片段:

 my $sel = $dbh1->prepare("select foo, bar from table1");
  $sel->execute;

  my $ins = $dbh2->prepare("insert into table2 (foo, bar) values (?,?)");
  my $fetch_tuple_sub = sub { $sel->fetchrow_arrayref };

  my @tuple_status;
  $rc = $ins->execute_for_fetch($fetch_tuple_sub, \@tuple_status);
  my @errors = grep { ref $_ } @tuple_status;

当与 mvp 的答案结合使用时,它应该会更快,特别是如果 DBD::DB2 有自己的 execute_for_fetch 方法(我不知道)。具有自己的 execute_for_fetch 方法的 DBD 通常会批量操作。但是,无论如何它应该快一点。

于 2013-01-08T08:52:26.460 回答
1

如果您每天都这样做,我会认为 DB2exportimport实用程序会是您的最佳选择。这种方式可能比多条 SQL语句快得多。INSERT

您可以使用 Perl 的模块执行此操作,但如果您需要在 Perl 脚本中完成此操作,则DBI可能必须使用或反引号。system

于 2013-01-08T10:27:29.010 回答
1

如果您可以将内容从源数据库发送到文件,您可以使用 LOAD 命令或 INGEST 实用程序。LOAD 非常快,因为它不使用日志。INGEST 是正常插入,但可以重新启动。

这些命令可以从 Perl 中调用,其余的由 DB2 完成。

但是,如果源数据库和目标数据库是 DB2,您可以在目标中联合源。这意味着,您可以在目标数据库中看到远程表(来自源)。在这种情况下,您只需要调用 LOAD,就可以了。它将最快,因为通信是在 DB2 和 DB2 之间进行的,而不是像这样 DB2 -> Perl -> DB2。

我认为让 DB2 来处理大表会更好,因为中间有 Perl。内存可能会爆炸,提交可能是一个问题,等等。

此外,根据您的 DB2 许可,您可以使用 Optim High Performance Unload,以便直接从表空间中提取表,而不是通过 SQL(较慢)。

于 2013-01-08T15:26:21.150 回答