【问题标题】:Perl with mysql, terribly slow, how to acceleratePerl 与 mysql, 非常慢, 如何加速
【发布时间】:2012-03-21 18:04:38
【问题描述】:
unit
id fir_name sec_name
author
id name unit_id
author_paper
id author_id paper_id

我要统一作者['same author'是指姓名相同,单位的fir_name相同],同时要更改author_paper表。

这是我的工作:

$conn->do('create index author_name on author (name)');
my $sqr = $conn->prepare("select name from author group by name having count(*) > 1");
$sqr->execute();
while(my @row = $sqr->fetchrow_array()) {
  my $dup_name = $row[0];
  $dup_name = formatHtml($dup_name);
    my $sqr2 = $conn->prepare("select id, unit_id from author where name = '$dup_name'");
    $sqr2->execute();

    my %fir_name_hash = ();
    while(my @row2 = $sqr2->fetchrow_array()) {
        my $author_id = $row2[0];
        my $unit_id = $row2[1];
        my $fir_name = getFirNameInUnit($conn, $unit_id);
        if (not exists $fir_name_hash{$fir_name}) {
            $fir_name_hash{$fir_name} = []; #anonymous arr reference
        }
        $x = $fir_name_hash{$fir_name};
        push @$x, $author_id;
    }

    while(my ($fir_name, $author_id_arr) = each(%fir_name_hash)) {
        my $count = scalar @$author_id_arr;
        if ($count == 1) {next;}
        my $author_id = $author_id_arr->[0];
        for ($i = 1; $i < $count; $i++) {
            #print "$author_id_arr->[$i] => $author_id\n";
            unifyAuthorAndAuthorPaperTable($conn, $author_id, $author_id_arr->[$i]); #just delete in author table, and update in author_paper table 
        }
    }
}

从作者中选择计数(*); #240,000 从作者中选择计数(不同(名称)); #7,7000 它非常慢!!我已经运行了 5 个小时,它刚刚删除了大约 4,0000 个重复名称。 如何让它运行得更快。我渴望得到你的建议

【问题讨论】:

标签: mysql performance perl


【解决方案1】:

当我看到查询和循环时,我认为您遇到了延迟问题:您查询以获取一组值,然后遍历该组以执行其他操作。如果这意味着集合中的每一行都需要通过网络往返于数据库,那将是一个很大的延迟。

如果您可以使用 UPDATE 和子选择在单个查询中执行此操作,或者如果您可以批处理这些请求并在一次往返中执行所有这些请求,那就更好了。

如果您明智地使用索引,您将获得额外的加速。 WHERE 子句中的每一列都应该有一个索引。每个外键都应该有一个索引。

我会对您的查询运行 EXPLAIN PLAN 并查看是否有任何 TABLE SCAN 正在进行。如果有,您必须正确索引。

我想知道一个设计合理的 JOIN 是否会帮助你?

一个表中的 240,000 行和另一个表中的 77,000 行并不是那么大型数据库。

【讨论】:

  • 你是对的。我也不喜欢那个循环。他不会使用 SQL,可能不知道如何编写复杂的查询。
【解决方案2】:

你不应该在循环中准备第二条sql语句,你可以在使用?占位符时真正使用准备:

$conn->do('create index author_name on author (name)');

my $sqr = $conn->prepare('select name from author group by name having count(*) > 1');

# ? is the placeholder and the database driver knows if its an integer or a string and 
# quotes the input if needed.
my $sqr2 = $conn->prepare('select id, unit_id from author where name = ?');

$sqr->execute();
while(my @row = $sqr->fetchrow_array()) {
  my $dup_name = $row[0];
  $dup_name = formatHtml($dup_name);

    # Now you can reuse the prepared handle with different input
    $sqr2->execute( $dup_name );

    my %fir_name_hash = ();
    while(my @row2 = $sqr2->fetchrow_array()) {
        my $author_id = $row2[0];
        my $unit_id = $row2[1];
        my $fir_name = getFirNameInUnit($conn, $unit_id);
        if (not exists $fir_name_hash{$fir_name}) {
            $fir_name_hash{$fir_name} = []; #anonymous arr reference
        }
        $x = $fir_name_hash{$fir_name};
        push @$x, $author_id;
    }

    while(my ($fir_name, $author_id_arr) = each(%fir_name_hash)) {
        my $count = scalar @$author_id_arr;
        if ($count == 1) {next;}
        my $author_id = $author_id_arr->[0];
        for ($i = 1; $i < $count; $i++) {
            #print "$author_id_arr->[$i] => $author_id\n";
            unifyAuthorAndAuthorPaperTable($conn, $author_id, $author_id_arr->[$i]); #just delete in author table, and update in author_paper table 
        }
    }
}

这也应该加快速度。

【讨论】:

  • 这确实加快了很多。另见link
猜你喜欢
  • 2012-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多