我的建议是,不要使用数据库。在此类任务中,编写良好的 perl 脚本将在数量级上胜过数据库。相信我,我有很多实践经验。当 perl 完成时,您不会将数据导入数据库。
当你用 800 个字符写 1500000 行时,对我来说似乎是 1.2GB。如果您的磁盘速度非常慢(30MB/s),您将在 40 秒内读取它。更好的 50 -> 24s,100 -> 12s 等等。但是 2GHz CPU 上的 perl 哈希查找(如 db join)速度高于 5Mlookups/s。这意味着您的 CPU 绑定工作将在几秒钟内完成,而您的 IO 绑定工作将在几十秒内完成。如果真的是 10GB,数字会改变,但比例是一样的。
您尚未指定数据修改是否更改大小(如果可以就地进行修改),因此我们不会假设它并将用作过滤器。您尚未指定“修改文件”的格式和修改类型。假设它由选项卡分隔,例如:
<id><tab><position_after_id><tab><amount><tab><data>
我们将从标准输入读取数据并写入标准输出,脚本可以是这样的:
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 数据大约需要半分钟。对于 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 }