2016-10-03 75 views
-2

這裏是我的腳本:優化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記錄。

請提出建議,如果有任何方法可以改進我的腳本以獲得更快的結果。

+4

它會更容易找出你想,如果你沒有使用一個做字母變量名稱,但使用描述性名稱。請用更好的變量重新編寫你的問題,這樣我們就可以繼續。 – xxfelixxx

+0

不要對此使用數組:'@contact_list = <$handle>;',while while while while while(my $ contact_row = <$handle>){chomp($ contact_row);做東西; }'關閉$ handle;並遵循@xxfelixxx說明。 – AbhiNickz

+0

http://unix.stackexchange.com/questions/134829/compare-two-columns-of-different-files-and-print-if-it-matches – xxfelixxx

回答

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. 的方式你這樣做,我打賭大部分時間在umcompressing數據庫轉儲(這會發生370K次)度過的。解壓一次 - 在做比賽之前。 (假設你有足夠的磁盤)。
  2. 如果不檢查實際的正則表達式,fgrep一樣會節省一些(邊際)時間(雖然我懷疑這optimizatin在內部被grep的完成)對不啜文件
  3. 的建議是內存節約的好,並且對數據的單次掃描不會影響速度。然而,你實際上不必要地掃描多次,以擺脫重複的聯繫人

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

而且並不總是減緩了整個事情下來,@contact_list在存儲器拷貝還浪費內存。

您可以通過讀取線,跟蹤在哈希,並跳過循環體的重複:

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