Мне поручено модифицировать скрипт Perl, который читает 12 файлов (~ 1 ГБ каждый с ~ 4 миллионами записей/файлов). Проблема в том, что я не знаю никаких perl. Тем не менее, мне удалось успешно изменить сценарий для моего варианта использования. Проблема в том, что сценарий занимает огромное количество времени для обработки файла, а также для вставки записей в базу данных. Любые указатели/предложения по сокращению времени будут оценены.Perl: обработка больших файлов и сохранение в базе данных
В качестве примера строка ввода (изменен, чтобы защитить идентичность) от одного из файлов выглядит следующим образом:
10.0.0.25 [06/Aug/2015:06:00:02 +0000] "0.002" "200" "0.002" "172.16.2.57:7777" "-" "GET /txt/AKXBPPYICZIBGM/n1/19757_705326?dc=us2&ext_user_id=1400587512&si=149042592 HTTP/1.1" "http://xyz.xyz/site_view.xhtml?cmid=22211051&get-title=Test%20-%20Test%20Test%2010&Test=Test%20Test"
Сценарий (смешанный с некоторым псевдо-кода) выглядит следующим образом:
for ($i = 0 ; $i < 12 ; $i++) {
$img_log_path = "Set appropriate path according to the iteration";
open(IMG_HANDLE, $img_log_path) or "Could not open the file $0\n";
while ($line = <IMG_HANDLE>) {
my $impression_date = `date --date="yesterday" +%Y-%m-%d`;
chomp $line;
if ($line =~ m/&si=(\d+)/ig) {
$affid = $1; # Extract the affiliate ID from $line
@fields = split(/"/, $line);
$img_ref_url = $fields[13]; # Extract the impression URL from $line
$impression_urls{$affid}{$img_ref_url}{IMPRESSION_COUNT}++; # Store the beacon impression URLs along with a count of number of impressions
$img_ref_url =~ m/http:\/\/(.*?)\//i;
$impression_urls{$affid}{$img_ref_url}{IMPRESSION_URL_HOST} = $1; # Store the hostname of the $img_ref_url
# Store the time at which first impression occurs for this URL.
$line =~ m/(\d\d:\d\d:\d\d)\s/ig;
my $impression_url_time = $1;
my $impression_time = split(/ /,$impression_urls{$affid}{$img_ref_url}{IMPRESSION_TIME}); # If IMPRESSION_TIME exists for this URL from a previous impression then extract the time
# Store the time for the first impression
if($impression_url_time lt $impression_time || !defined($impression_urls{$affid}{$img_ref_url}{IMPRESSION_TIME})) {
$impression_urls{$affid}{$ref}{IMPRESSION_TIME} = "$impression_date "."$impression_url_time"; # Store the time at which the first impression happened for this URL.
}
if ((defined($affid) && $affid ne "") && (defined($img_ref_url) && $img_ref_url ne "")) {
$affiliates{$affid}{TOTAL_IMP}++; # Increment the total number of impressions for this URL.
if (&CheckURL($img_ref_url)) {
$affiliates{$affid}{ADULT_IMP}++;
}
}
}
}
close IMG_HANDLE;
}
for $aff_id (@aff_ids) { #@aff_ids contains all the affiliate ids from a database
my $impression_table = "tns_impressions";
foreach $impression_url (keys %{ $impression_urls{$aff_id} }) {
# If the pageurl doesn't exist then don't add it into the database
if ($impression_url =~ /-/) {
next;
}
# Insert the URL into the database
my $query = "INSERT INTO $impression_table (affiliate_id, impression_url, created_at, no_of_impressions, hostname) VALUES (?,?,?,?,?)";
my $statement = $dbh->prepare($query)
or print STDERR "$dbh->errstr";
$statement->execute(
$aff_id,
$impression_url,
$impression_urls{$aff_id}{$impression_url}{IMPRESSION_TIME},
$impression_urls{$aff_id}{$impression_url}{IMPRESSION_COUNT},
$impression_urls{$aff_id}{$impression_url}{IMPRESSION_URL_HOST}
) or print STDERR "$statement->errstr";
}
}
Move '$ impression_date' и подготовить заявление из цикла для закуска. –
@ Hynek-Pichi-Vychodil MySQL. Требуется около 1 часа для обработки каждого файла и 1 час для вставки в базу данных на файл. –
@ Сухой27 Ваше решение сработало. –