2017-01-17 2 views
1

요구 사항

은 내가 직렬화 복원 된 개체를 나중에 파일을 읽고 얻을 수있는 방법으로 파일에 드리프트 - 직렬화 된 객체의 스트림을 저장해야합니다.
  • 개체의 유형이 다를 수 있습니다. 파일의 각 객체를 구분하는 가장 좋은 방법은 무엇
  • 질문

    (I). 예를 들어, 텍스트 파일에서 개행 문자로 각 객체를 분리 할 수 ​​있습니다. 바이너리 파일에도이 방법이 유효합니까?저장 중고품 - 직렬화 된 객체

    (ii) 역 직렬화 중에 사용할 각 객체의 유형을 표시하려면 각 바이트 시퀀스의 시작 부분에 유형 필드를 추가 할 계획입니다. 더 나은 접근 방법이 있습니까?

    답변

    1

    가장 중요한 질문은 파일에 액세스하는 방법입니다. 순차적 액세스 또는 임의 액세스?

    순차 액세스 (일종의) 또는 소수의 데이터

    파일의 각 객체를 구분하는 가장 좋은 방법은 무엇

    . 예를 들어, 텍스트 파일에서 개행 문자로 각 객체를 분리 할 수 ​​있습니다. 바이너리 파일에도이 방법이 유효합니까?

    분명히 ;-). 그러나 더 나은 솔루션이 있다는 것에 대해 걱정하지 마십시오. 데이터 목록을 저장하려면 문자 그대로 list<data>을 저장할 수 있습니다. 우리는 여전히 읽고 한 번에 모든 것을 쓰기 때문에

    struct foo { 1: string field, 2: i32 otherfield } 
    
    struct bar { 1: map<string,wtf> seinfield, 2: double cloverfield } 
    
    struct wtf { 1: list<double> even_more_fields } 
    
    union MyDataRecord { 
        1: foo foo 
        2: bar bar 
        3: wtf wtf 
    } 
    
    list<MyDataRecord> 
    

    : 즉, 뭔가 같은 :

    struct foo { 1: string field, 2: i32 otherfield } 
    
    list<foo> 
    

    데이터는 foo하지만, 유형을 변화의 사이에 노동 조합을 넣어하지 않는 경우 인공 리미터가 필요 없습니다.

    (역 직렬화 중에 사용할) 각 개체의 형식을 표시하려면 각 바이트 시퀀스의 시작 부분에 형식 필드를 추가 할 계획입니다. 더 나은 접근 방법이 있습니까?

    위에서 설명한 것처럼 데이터를 list<>에 넣으면 Thrift가 처리합니다. 전체 목록을 읽고 쓰는 것만으로도 충분합니다. 당신이 당신의 데이터에 대한 랜덤 액세스를 원하는 경우

    랜덤 액세스 및/또는 데이터의 많은

    상황이 극적으로 변경됩니다. 이 문제는 효율적이고 신속하게하기 위해서 항상 파일 전체를 스캔하지 않고 파일에서 주어진 요소의 위치를 ​​결정해야합니다.1). 대부분의 경우, 기록되는 항목의 바이트 크기는 다양합니다. 그들 모두가 한 종류 foo의 경우에도 단지, 하나는 여전히 foo 변수 크기의 데이터 멤버를 가지고 있기 때문에 특정 요소가

    position = sizeof(foo) * index_of_desired_element 
    

    에 있다고 가정 할 수 다음 string 필드.

    이 문제를 해결하기 위해 기본적으로 두 가지 옵션이 있습니다.

    (1) 고정 크기 레코드 : 모든 요소가 미리 정의 된 최대 크기를 초과하지 않도록하고 파일 레코드 크기로 사용할 수 있습니다. list<>을 더 이상 사용하지 않고 파일의 올바른 위치에 데이터를 기록합니다. n 번째 요소의 위치는 다시

    position = N * predefined_record_size 
    

    단점 우리가 잠재적으로 많은 공간 플러스 데이터의 제한된 크기를 낭비하는 것이보다 분명하다.

    (2) 인덱스 파일 : 두 번째 옵션은 데이터 파일의 각 항목의 위치를 ​​보유하는 별도의 인덱스 파일을 유지 관리하는 것입니다. 이것은 다시 정수의 간단한 목록 수 :

    list<i32> 
    

    여기 단점은, 인덱스 특히 삽입에 적절한 모양에 있는지 확인 파일의 중간에 삭제 작업을 업데이트 할 필요가있다 .

    위의 두 가지 옵션의 일반적인 문제는 많은 데이터를 이동해야하기 때문에 삽입 및 삭제 작업이 어려워 질 수 있다는 것입니다. 이를 처리하기 위해 마커 삭제와 같은 특수 효과를 솔루션에 추가하는 것을 발견하게됩니다.

    당신의 데이터 만 잔뜩 가지고

    경우 결론은 list<union> 접근 방식은 당신이 찾고있는 무엇을 수 있습니다. union은 언제든지 확장 가능하므로 나중에 다른 요소를 추가 할 수 있습니다.

    데이터에만 순차적으로 액세스하려는 경우 list<union> 접근 방식을 선택하거나 union 요소를 하나씩 읽거나 쓰십시오. Thrift는 불필요한 데이터를 건너 뛸 수있는 기능을 지원합니다 (Skip()).

    그러나 임의로 데이터에 액세스하고 많은 양의 데이터를 처리하려는 경우 실제 데이터베이스가 더 적합 할 수 있습니다. 레코드 구분자에 대한 잠재적 큰 파일을 검색


    1)the kind of O(?) you want 아니다.

    +0

    설명해 주셔서 감사합니다. 나의 유스 케이스는 순차적 접근이다. 그러나 인덱스 파일을 유지 관리하는 대신 레코드 크기와 레코드 크기를 함께 저장하는 것이 좋습니다. 예를 들어 모든 레코드의 처음 4 바이트는 레코드를 구성하는 바이트 수를 나타냅니다 (레코드가 4GB보다 크지 않다고 가정). 이렇게하면 절대 오프셋을 저장할 필요가 없으며 삽입/삭제를 더 쉽게 수행 할 수 있습니다. – jithinpt

    +0

    '124.657.013' 레코드의 인덱스 '15.883.127'에있는 항목을 검색, 삽입 또는 삭제하는 것이 실제로는 O (1) 작업인지 아니면 적어도 O (1) 작업인지에 관계없이 데이터 파일이 몇 GB에 걸쳐 있다고 가정하십시오. (logN)'알고리즘을 사용하고 있습니까? ** 데이터 항목이 10 개 밖에없는 경우 거의 모든 알고리즘이 빠릅니다. **. – JensG

    +0

    아직도하고 싶다면'TFramedProtocol'을보십시오. 그것은 정확하게 그것을 수행하고 출력 스트림에 i32로 따라갈 데이터 프레임의 크기를 씁니다. – JensG