0

ストアのログ ファイルを読み取る必要があります。ログには、アイテム ID と、その後に「sold」という単語が表示されます。そこで、このファイルを読み取るスクリプトを作成し、アイテム ID ごとに "sold" という単語が何回出現するかを数えました。アイテムには多くの「所有者」がいることがわかります。つまり、"owner_id" (私の DB のデータ) と "item_id" の間に関係があります。所有者が 1 日あたりに販売するアイテムの数を知りたいので、"%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 メソッドを 1 回だけ呼び出したいと考えています。

一番!

4

1 に答える 1

1

ロジックを 2 つのループに分けます。

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()、そのコードの一般的な形でそれが行われるはずです。

一般に、データベースは行のセットをフェッチするのが得意なので、DB からフェッチする呼び出しを最小限に抑えるのは正しいことです。

于 2013-06-11T08:35:31.157 に答える