2014-02-26 81 views
1

目前我有一個比較兩個表的要求,每個表有700M +左右的記錄。使用Perl比較2個文件

根據我們的數據庫性能,我們想出了一個基於文件進行比較的想法,而不是將它帶到數據庫。還聽說Perl比任何其他編碼方法都快得多

我們需要將一個文件中的使用計劃與另一個文件中的相同移動數字進行比較,如果存在且其用法匹配或不匹配,我們需要在新文件中只寫入不匹配的記錄。

實施例:

文件1

number, Usage type , Usage Plan , Usage Volume (KB) ........ 
12344 , CP   , FB   , 100 ........ 
12323 , UP   , FB   , 200 ........ 
12322 , CP   , G+   , 300 ........ 

文件2

number, Usage type , Usage Plan , Usage Volume (KB) ........ 
12344 , CP   , FB   , 100 ........ 
12323 , UP   , FB   , 210 ........ 

因此,在上述情況下我UNMATCH文件應包含

UNMATCH文件

12323 , UP   , FB   , 210 ........ 
12322 , CP   , G+   , 300 ........ 

........意思是在這之後有很多列,我們不會用它來比較。它們更像是有關該計劃的更多細節。

請在此分享您的建議和編碼想法。

我們的目標是要完成6中的比較 - 7小時..所以那個負荷和其他的東西可以在2天內完成..

在此先感謝.. 山姆

+2

你試過了什麼?另外,文件1中的每行都保證存在於文件2中?每個文件中的記錄是否以相同的順序? – daotoad

+0

它不保證它會存在,也不會按排序順序。 – user2769015

+2

您似乎忘記了指定遇到了什麼問題。 – ikegami

回答

-1

這個怎麼樣:

use strict; 

open FILE1, 'file1.txt'; 
open FILE2, 'file2.txt'; 
open OUTPUT, '>output.txt'; 

my $regex = qr/^ *(\d+) , (.*) , (.*) , (\d+)/; 

my $file1; 
while(<FILE1>){ 
    if(/$regex/){ 
    $file1->{$1}->{type} = $2; 
    $file1->{$1}->{plan} = $3; 
    $file1->{$1}->{volume} = $4; 
    } 
} 

my $file2; 
while(<FILE2>){ 
    if(/$regex/){ 
    $file2->{$1}->{type} = $2; 
    $file2->{$1}->{plan} = $3; 
    $file2->{$1}->{volume} = $4; 
    } 
} 

my $numbers; 
$numbers->{$_} = 1 foreach keys %$file1; 
$numbers->{$_} = 1 foreach keys %$file2; 

my $output; 
foreach(keys %$numbers){ 
    if(defined $file1->{$_} && defined $file2->{$_}){ 
    if($file1->{$_}->{type} ne $file2->{$_}->{type} || $file1->{$_}->{plan} ne $file2->{$_}->{plan} || $file1->{$_}->{volume} ne $file2->{$_}->{volume}){ 
     push @$output, [$_, $file2->{$_}->{type}, $file2->{$_}->{plan}, $file2->{$_}->{volume}]; 
    } 
    }elsif(defined $file1->{$_}){ 
    push @$output, [$_, $file1->{$_}->{type}, $file1->{$_}->{plan}, $file1->{$_}->{volume}]; 
    }else{ 
    push @$output, [$_, $file2->{$_}->{type}, $file2->{$_}->{plan}, $file2->{$_}->{volume}]; 
    } 
} 

print OUTPUT join(' , ', @$_)."\n" foreach @$output; 
+0

謝謝,將對其進行處理並更新您。 – user2769015

+0

我提出的解決方案適用於靜態文件和不斷修改的文件。如果您在特定時間執行代碼,您將獲得該特定時間的輸出。當一個文件改變時,你應該再次執行以獲得新的輸出。您可以在Linux下使用「cron」或Windows下的「計劃任務」(和朋友)自動執行此操作 – Aldo

0

這是另一種不會將整個文件讀入內存的方式,這可能是由於內存限制導致的問題。例如,700M記錄×30字節/記錄= 21GB文件。

它確實需要從數據庫導出數據時按數字對文件進行排序。假設數量正在增加。

open FILE1, "file1"; 
open FILE2, "file2"; 
open OUT, ">out.txt"; 

$line1 = <FILE1>; 
$line2 = <FILE2>; 

sub number_part { 
    ($line) = @_; 
    return $1 if $line =~ /^(\d{1..9})/; 
} 

while (1) { 
    if ($line1 eq $line2) { 
     $line1 = <FILE1>; 
     $line2 = <FILE2>; 

    } elsif (number_part(line1) == number_part(line2)) { 
     print OUT $line1; 
     print OUT $line2; 
     $line1 = <FILE1>; 
     $line2 = <FILE2>; 

    } elsif (number_part($line1) < number_part($line2)) { 
     print OUT $line1; 
     $line1 = <FILE1>; 

    } elsif (number_part(line1) > number_part(line2)) { 
     print OUT $line2; 
     $line2 = <FILE2>; 
    } 

    # Use a dummy record if EOF is reached for either file. 
    # Done when EOF is reached for both files. 
    $line1 = "9999999999" unless $line1; 
    $line2 = "9999999999" unless $line2 
    last if $line eq "999999999" and $line2 eq "9999999999"; 
} 

close(FILE1); 
close(FILE2); 
close(OUT);