1

下面是将 SQL 查询转储为对齐的文本表格式的代码。

sub sql_command {
    my ($self,$str) = @_;
    my $s = $self->{_db}->prepare($str) or die $!;
    $s->execute() or die $!;
    my $table;
    push @$table, [ map { defined $_ ? $_ : "undef" } @{$s->{'NAME'}}];
    while(my $row = $s->fetch) {
          push @$table, [ map{ defined $_ ? $_ : "undef" }@$row ];
    }
    return box_format($table);;
}


sub box_format {
    my $table = shift;
    my $n_cols = scalar @{$table->[0]};

    my $tb = Text::Table->new(\'| ', '', (\' | ','')x($n_cols-1), \' |+');
    $tb->load(@$table);
    my $rule = $tb->rule(qw/- +/);
    my @rows = $tb->body();
    return $rule, shift @rows, $rule, @rows, $rule
           if @rows;
}

输出符合预期。但在性能方面,处理大约 5MB 大小的输出文件需要大约 30 秒。

在性能方面是否有更好的方法来实现这一目标?

谢谢!

4

1 回答 1

2

该代码有几个可能的性能问题。首先是在构建过程中,$table您将整个数据集拉入内存。这会消耗大量内存。当数据出来时,你会更好地格式化数据。这意味着Text::Table->load您将使用Text::Table->add.

sub sql_command {
    my ($self,$sql) = @_;
    my $sth = $self->{_db}->prepare($sql) or die $!;
    $sth->execute() or die $!;

    return box_format_from_query($sth);
}

sub box_format_from_query {
    my $sth = shift;
    my $headers = [ map { defined $_ ? $_ : "undef" } @{$s->{'NAME'}}];
    my $num_cols = @$headers;

    my $table = Text::Table->new(\'| ', '', (\' | ','')x($num_cols-1), \' |+');
    while(my $row = $s->fetch) {
          $table->add(map { defined $_ ? $_ : "undef" } @$row );
    }

    my $rule = $tb->rule(qw/- +/);
    my @rows = $tb->body();
    return $rule, shift @rows, $rule, @rows, $rule
           if @rows;
}

第二个性能问题可能是 Text::Table 本身。由于表方法适用于数据的副本(也就是说,您不会将数据作为引用传递),因此不太可能在编写时考虑到大型数据集。找出答案的唯一方法是分析您的代码。看看Devel::NYTProf。您应该能够弄清楚您的代码在哪里花费时间。如果结果是在 Text::Table 方法中,您应该联系作者或考虑另一种生成格式化输出的方法。

第三个性能问题可能是您的查询。您没有显示您的查询,但它完全有可能效率低下。Devel::NYTProf 会告诉您是否在$sth->execute. 如果是这样,你还有另一个问题要问。:)

于 2013-03-12T13:18:41.833 回答