私の提案は、データベースを使用しないことです。適切に作成された perl スクリプトは、この種のタスクでデータベースよりも優れたパフォーマンスを発揮します。私を信じてください、私はそれについて多くの実践的な経験を持っています. perl が終了すると、データベースにデータがインポートされません。
800文字で1500000行を書くと、私には1.2GBのようです。非常に遅いディスク (30MB/秒) を使用する場合は、40 秒で読み取ります。より良い 50 -> 24 秒、100 -> 12 秒など。しかし、2GHz CPU での perl ハッシュ ルックアップ (db join など) の速度は 5Mlookups/s を超えています。これは、CPU バウンドの作業が数秒で、IO バウンドの作業が数十秒になることを意味します。本当に 10GB の場合、数字は変わりますが、割合は同じです。
データの変更がサイズを変更するかどうか (変更をその場で行うことができる場合) を指定していないため、それを想定せず、フィルターとして機能します。「修飾子ファイル」の形式と変更の種類を指定していません。次のようなタブで区切られていると仮定します。
<id><tab><position_after_id><tab><amount><tab><data>
stdin からデータを読み取り、stdout に書き込みます。スクリプトは次のようになります。
my $modifier_filename = 'modifier_file.txt';
open my $mf, '<', $modifier_filename or die "Can't open '$modifier_filename': $!";
my %modifications;
while (<$mf>) {
chomp;
my ($id, $position, $amount, $data) = split /\t/;
$modifications{$id} = [$position, $amount, $data];
}
close $mf;
# make matching regexp (use quotemeta to prevent regexp meaningful characters)
my $id_regexp = join '|', map quotemeta, keys %modifications;
$id_regexp = qr/($id_regexp)/; # compile regexp
while (<>) {
next unless m/$id_regexp/;
next unless $modifications{$1};
my ($position, $amount, $data) = @{$modifications{$1}};
substr $_, $+[1] + $position, $amount, $data;
}
continue { print }
私のラップトップでは、150 万行、1800 のルックアップ ID、1.2GB のデータに約 30 分かかります。10GB の場合、5 分を超えてはなりません。あなたにとって合理的な速さですか?
IO バウンドではなく (たとえば、NAS を使用している場合)、CPU バウンドであると考え始める場合は、読みやすさを犠牲にして、次のように変更できます。
my $mod;
while (<>) {
next unless m/$id_regexp/;
$mod = $modifications{$1};
next unless $mod;
substr $_, $+[1] + $mod->[0], $mod->[1], $mod->[2];
}
continue { print }