0

我必须阅读商店的日志文件。日志显示项目 ID 和后面的“已售”字样。所以我编写了一个脚本来读取这个文件,计算每个项目 id 出现的单词“sold”的次数。事实证明,这些物品有很多“所有者”。也就是说,“owner_id”(我的数据库中的数据)和“item_id”之间存在关系。我想知道所有者每天卖出多少物品,所以我创建了一个“%item_id_owner_map”:

my %item_id_sold_times;
my %item_id_owner_map;

open my $infile, "<", $file_location or die("$!: $file_location");
while (<$infile>) {
    if (/item_id:(\d+)\s*,\s*sold/) {
        my $item_id = $1;
        $item_id_sold_times{$item_id}++;
        my $owner_ids =
          Store::Model::Map::ItemOwnerMap->fetch_by_keys( [$item_id] )
          ->entry();
        for my $owner_id (@$owner_ids) {
            $item_id_owner_map{$owner_id}++;
        }
    }
}
close $infile;

“Store::Model::Map::ItemOwnerMap->fetch_by_keys([$item_id])->entry();” 方法将 item_id 或 ids 作为输入,并返回 owner_id 作为输出。

一切看起来都很棒,但实际上,您会看到每次 Perl 找到一个正则表达式匹配项(即每次应用“if”条件时),我的脚本都会调用“Store::Model::Map::ItemOwnerMap->fetch_by_keys”方法,这是非常昂贵的,因为这些日志文件非常非常长。

有没有办法让我的脚本更有效率?如果可能的话,我只想调用我的 Model 方法一次。

最好的!

4

1 回答 1

1

将您的逻辑分成两个循环:

while (<$infile>) {
    if (/item_id:(\d+)\s*,\s*sold/) {
        my $item_id = $1;
        $item_id_sold_times{$item_id}++;
    }
}
my @matched_items_ids = keys %item_id_sold_times;
my $owner_ids =
  Store::Model::Map::ItemOwnerMap->fetch_by_keys( \@matched_item_ids )
  ->entry();
for my $owner_id (@$owner_ids) {
    $item_id_owner_map{$owner_id}++;
}

我不知道entry()调用是否正确,但是该代码的一般形式应该可以为您完成。

一般来说,数据库擅长获取行集,因此您可以最大限度地减少从数据库中获取的调用。

于 2013-06-11T08:35:31.157 回答