2009-05-20 4 views
1

요구 사항은 다음과 같습니다파일에 기록을 비교 및보고 통계 - 시나리오 1

사실 1 : 우리는 레거시 시스템에 의해 생산 된 일부 데이터 파일이

사실 2 : 우리는 새로운 생산 일부 데이터 파일이 결국 기존 하나

사실을 교체해야 시스템은 3 :

  1. 두 파일은 텍스트/ASCII 파일, 레코드 는 0,123,516으로 구성되고있다여러 줄.
  2. 레코드의 각 줄은 의 필드 이름과 필드 값으로 구성됩니다. 선이 제시되는
  3. 형식은 1 2하지만 필드 명 및 fieldValue의 는
  4. 필드 이름 1 (2) 사이에 변경 정규식의 사용을 통해 각 라인 로부터 추출 될 수 있지만, 사이 다르다 그들에게
  5. 각 레코드는 두 시스템에서 동일하지 않을 을 필요로 우리가 출력 파일에 기록 주문으로 새 레코드와 기존 기록을 관련하는 데 도움이되는 고유 식별자 을 가지고에 관한 것을 우리는 매핑이있다. 우리는 새로운 시스템을 구축하지만 반복 때, 우리가 비교해야로서 : 35 MB

사실 4-

  • 비교하는 각 파일 (30)의 평균 경우에 10메가바이트의 최소 두 시스템에서 정확히 동일한 조건에서 생성 된 파일을 비교하여 차이점을 조정합니다.

    사실 5 :이 비교 작업은 값 비싼 시각적 diff 도구를 사용하여 수동으로 수행됩니다. 이를 돕기 위해 두 개의 다른 필드 이름을 공통 이름으로 가져온 다음 각 파일의 각 레코드에서 필드 이름을 정렬하여 순서대로 동기화하는 도구를 작성했습니다 (새 파일에는 무시되는 추가 필드가있을 수 있음). 시각적 차이)

    사실 6 : 사람이 수동으로 비교를 수행하고 인간이 실수를 저지르기 때문에 우리는 우리의 타임 라인에 중대한 영향을 미치는 잘못된 posetives와 네거티브를 얻고 있습니다.

    물론 'ALG'와 'DS'는 무엇이되어야합니까?

    내가 해결해야하는 시나리오 :

    사람들이 시각은 diff를 검사하기 위해 계속

    - 대부분의 처리는 라인의 배열을 정렬 것 같다 -이에서 exsiting 스크립트의 성능이 음침한 lexicographic order (배열 요소를 읽고/가져 오는 것 : Tie :: File :: FETCH, Tie :: File :: Cache :: lookup 그리고 그것을 올바른 위치에 두는 것은 Tie :: File :: Cache :: insert, 타이 :: 파일 :: 힙 :: 삽입)

    use strict; 
    use warnings; 
    
    use Tie::File; 
    
    use Data::Dumper; 
    
    use Digest::MD5 qw(md5_hex); 
    
    # open an existing file in read-only mode 
    use Fcntl 'O_RDONLY'; 
    
    die "Usage: $0 <unsorted input filename> <sorted output filename>" if ($#ARGV < 1); 
    
    our $recordsWrittenCount = 0; 
    our $fieldsSorted = 0; 
    
    our @array; 
    
    tie @array, 'Tie::File', $ARGV[0], memory => 50_000_000, mode => O_RDONLY or die "Cannot open $ARGV[0]: $!"; 
    
    open(OUTFILE, ">" . $ARGV[1]) or die "Cannot open $ARGV[1]: $!"; 
    
    our @tempRecordStorage =(); 
    
    our $dx = 0; 
    
    # Now read in the EL6 file 
    
    our $numberOfLines = @array; # accessing @array in a loop might be expensive as it is tied?? 
    
    for($dx = 0; $dx < $numberOfLines; ++$dx) 
    { 
        if($array[$dx] eq 'RECORD') 
        { 
         ++$recordsWrittenCount; 
    
         my $endOfRecord = $dx; 
    
         until($array[++$endOfRecord] eq '.') 
         { 
          push @tempRecordStorage, $array[$endOfRecord]; 
          ++$fieldsSorted; 
         } 
    
         print OUTFILE "RECORD\n"; 
    
         local $, = "\n"; 
         print OUTFILE sort @tempRecordStorage; 
         @tempRecordStorage =(); 
    
         print OUTFILE "\n.\n"; # PERL does not postfix trailing separator after the last array element, so we need to do this ourselves) 
    
         $dx = $endOfRecord;  
        } 
    } 
    
    close(OUTFILE); 
    
    # Display results to user 
    
    print "\n[*] Done: " . $fieldsSorted . " fields sorted from " . $recordsWrittenCount . " records written.\n"; 
    

    그래서 나는 그것에 대해 생각하고 내가 생각하는 트라이, 어쩌면 접미사 트라이/PATRICIA의 트라이 경우, 삽입 itsel에 그래서 어떤 종류의 f 각 레코드의 필드가 정렬됩니다. 따라서 최종 배열을 모두 한 번에 정렬 할 필요가 없으며 비용이 상각됩니다 (내 부분에 대한 추론)

    또 다른 문제가 발생합니다. Tie :: File은 배열을 사용하여 행을 추상화합니다. 트리에 줄을 읽고 배열로 다시 직렬화하는 파일은 추가 메모리와 처리가 필요합니다./

    질문 - 묶인 배열을 정렬하는 데 드는 비용보다 많은 비용이 들지 않습니까?

  • 답변

    2

    Tie :: 파일이 매우 느립니다. 두 가지 이유가 있습니다. 첫째, 묶인 변수는 표준 변수보다 훨씬 느립니다. 다른 이유는 Tie :: File의 경우 배열의 데이터가 메모리가 아닌 디스크에 있기 때문입니다. 이렇게하면 액세스가 크게 느려집니다. Tie :: File의 캐시는 일부 상황에서는 성능을 향상시킬 수 있지만 여기에서 수행 할 때 한 번에 한 요소 씩 루프를 반복 할 때 유용하지는 않습니다. (캐시는 동일한 색인을 다시 방문 할 때만 도움이됩니다.) Tie :: File을 사용하는 시간은 모든 데이터를 한 번에 메모리에 저장해야하는 알고리즘이 있지만 이렇게 할 메모리가 충분하지 않은 경우입니다. Tie :: File을 사용하여 한 번에 한 줄씩 만 파일을 처리하므로 무의미 할뿐만 아니라 해가됩니다.

    트라이가 올바른 선택이라고 생각하지 않습니다. 대신에 일반 HoH (해시 해시)를 사용합니다. 파일은 크기가 작아서 한 번에 모든 것을 메모리에서 가져올 수 있어야합니다. 나는 각각의 파일을 구문 분석하고 다음과 같습니다 해시를 구축하는 것이 좋습니다

    %data = (
        id1 => { 
        field1 => value1, 
        field2 => value2, 
        }, 
        id2 => { 
        field1 => value1, 
        field2 => value2, 
        }, 
    ); 
    

    당신이 비교가 쉽게 할 것이다 데이터 구조를 구축하는 동안 필드 이름을 정상화하기 위해 매핑을 사용하는 경우.

    1. 두 해시의 키 세트 비교를 수행

      이 작업을 수행, 데이터를 비교합니다. 이렇게하면 세 가지 목록이 생성됩니다. 기존 데이터에있는 ID, 새 데이터에있는 ID 및 둘 다에있는 ID입니다.
    2. 하나의 데이터 세트에만 나타나는 ID 목록을보고하십시오. 이들은 다른 데이터 세트에 해당 레코드가없는 레코드입니다.
    3. 두 데이터 세트의 ID에 대해 각 ID 필드의 데이터를 필드별로 비교하고 차이점을보고하십시오.