Я предлагаю не использовать базу данных. Хорошо написанный сценарий Perl будет превосходить базу данных в таком порядке. Поверьте мне, у меня есть много практического опыта с этим. Вы не будете импортировать данные в базу данных, когда Perl будет завершен.
Когда вы пишете 1500000 строк с 800 символами, мне кажется, что это 1,2 ГБ. Если у вас очень медленный диск (30 МБ / с), вы прочитаете его за 40 секунд. С лучшими 50 -> 24 с, 100 -> 12 с и так. Но скорость поиска perl hash (например, db join) на 2 ГГц процессоре выше 5Mlookups / s. Это означает, что работа, связанная с вашим ЦП, займет несколько секунд, а работа, связанная с вводом-выводом, - за десятки секунд. Если это действительно 10 ГБ, номера изменятся, но пропорция будет такой же.
Вы не указали, меняет ли модификация данных размер или нет (если модификация может быть выполнена на месте), поэтому мы не будем предполагать это и будем работать как фильтр. Вы не указали, в каком формате находится ваш «файл модификатора» и какие модификации. Предположим, что он разделен табуляцией чем-то вроде:
<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 }
На моем ноутбуке требуется около полуминуты для 1,5 миллиона строк, 1800 идентификаторов поиска, 1,2 ГБ данных. Для 10GB это не должно быть более 5 минут. Это достаточно быстро для вас?
Если вы начинаете думать, что вы не привязаны к IO (например, если используете какое-то NAS), но привязаны к процессору, вы можете пожертвовать некоторой читабельностью и перейти к этому:
my $mod;
while (<>) {
next unless m/$id_regexp/;
$mod = $modifications{$1};
next unless $mod;
substr $_, $+[1] + $mod->[0], $mod->[1], $mod->[2];
}
continue { print }