优化Perl脚本以处理大量数据

时间:2016-10-03 08:01:25

标签: perl

这是我的剧本:

#!/usr/bin/perl -w

use warnings;
use strict;
no warnings 'uninitialized';

`rm /slot/ems12093/oracle/working/marchfound.txt`;
`touch /slot/ems12093/oracle/working/marchfound.txt`;

`rm /slot/ems12093/oracle/working/newcontact.txt`;
`touch /slot/ems12093/oracle/working/newcontact.txt`;

my ( $filename, $handle, @contact_list, $file_list, $k, @file_list2, $i, $e, $m, $fh, $f, $g,
    $file1, $data, $file_location, $arrSize, $namefile );

$file_location = '/slot/ems12093/oracle/working/marchfound.txt';
$filename      = '/slot/ems12093/oracle/working/contact.txt';

open( $handle, '<', $filename ) or die $!;
@contact_list = <$handle>;
close $handle;

chomp @contact_list;

chdir( '/scratch/mount_point/dnbfiles/oracle_cr/' );
$file_list = qx(ls|grep -i \"2016_03_Mar_EA\");
chomp( $file_list );

$k = "/scratch/mount_point/dnbfiles/oracle_cr/2016_03_Mar_EA";
chdir( $k );

@file_list2 = qx(ls|grep -i contact|grep -i full|grep -Ev "Glb");
chomp @file_list2;

foreach $file1 ( @file_list2 ) {

    foreach $i ( @contact_list ) {

        $e = "zgrep $i $file1";
        $f = qx($e);

        if ( $f ) {
            print "working\n";

            $g = "$f, $file1";

            open $data, '>>', $file_location or die $!;
            print $data "$g\n";
            close $data;

            @contact_list = grep { !/$i/ } @contact_list;
            $arrSize = @contact_list;
            print "$arrSize\n";
        }
    }

}

$m = "/slot/ems12093/oracle/working/";
chdir( $m );

chomp @contact_list;
$namefile = '/slot/ems12093/oracle/working/newcontact.txt';
open( $fh, '<', $namefile ) or die $!;
@contact_list = <$fh>;
close $fh;

print "done\n";

这里我正在获取一个输入文件contact.txt,该文件有370k条记录,例如邮件地址,并检查这些记录是否存在于3月份的压缩数据库2016_03_Mar_EA中。

该数据库再次包含约160万条记录,例如名称,名称,邮件等因此,需要花费大量时间来检查和打印所有355k * 1.6m的记录。

请建议我是否有任何方法可以改进我的脚本以获得更快的结果。

2 个答案:

答案 0 :(得分:3)

不是纯粹的速度特定,但你应该做以下修改。

1)contact.txt有370k记录,因此你不应该一次啜饮整个数据。所以不要做

@contact_list = <$handle>;

您应该使用

逐行读取数据
while(<$handle>){
    #process one contact at a time
}

2)您正在更改目录并执行shell命令以获取所需的文件。最好使用File::Find::Rule。它更容易使用,见下文:

my @files = File::Find::Rule->file()->name( '*.pm' )->in( @INC );

答案 1 :(得分:-1)

  1. 你这样做的方式,我敢打赌,大部分时间都用在umcompressing数据库转储上(这将发生370k次)。在进行比赛之前解压缩一次。 (假设你有足够的磁盘)。
  2. 如果你没有检查实际的正则表达式,fgrep将节省一些(边际)时间(虽然我怀疑这个优化是由grep内部完成的)
  3. 关于不啜饮文件的建议对于节省内存是有好处的,并且对于单次扫描数据不应该影响速度。但是,为了摆脱重复的联系人,你实际上是多次不必要地扫描arry,

    @contact_list = grep {!/ $ i /} @contact_list;

  4. 这并不总是减慢整个shebang,它也会浪费内存,因为@contact_list被复制到内存中。

    您可以逐行阅读,在哈希中跟踪,并跳过重复的循环体:

    next if exists $seen{$i};
    $seen{$i}++