2011-01-06 2 views
8

HBase에서 여러 행을 삭제하는 효율적인 방법이 있습니까? 아니면 HBase에 적합하지 않은 사용 사례 냄새가 있습니까?HBase에서 여러 행을 효율적으로 삭제하는 방법

'차트'라는 표가 있는데 차트에있는 항목이 포함되어 있습니다. chart|date_reversed|ranked_attribute_value_reversed|content_id

때때로 나는 주어진 날짜에 대한 차트를 재생하려면, 그래서에서 시작하는 모든 행을 삭제할 | '| date_reversed_2 차트'까지 '차트를 date_reversed_1를'행 키는 다음과 같은 형식으로되어 있습니다. 스캔으로 발견 된 각 행에 대해 삭제를 실행하는 것보다 나은 방법이 있습니까? 삭제할 모든 행은 서로 가깝게됩니다.

한 항목 (하나의 content_id)에 해당 항목의 여러 항목이있는 것을 원하지 않기 때문에 행을 삭제해야합니다 (해당 항목의 변경으로 인해 차트를 다시 생성해야하는 이유가됩니다) .

HBase 초보자이므로 열을 더 잘 사용할 수있는 행을 잘못 사용했을 수 있습니다. 설계 제안이 있으면 멋진 코드 일 것입니다. 또는 차트가 파일에서 더 잘 생성 된 것일 수 있습니다 (예 : 출력용 HBase 없음)? MapReduce를 사용하고 있습니다.

답변

7

먼저 HBase, AFAIK에서 범위 삭제가 발생하지 않습니다. 그러나 HTableInterface API에서 한 번에 두 개 이상의 행을 삭제하는 방법이 있습니다. 이를 위해 행 키가있는 Delete 객체를 스캔하여 List에 넣고 API를 사용합니다. 스캔 속도를 향상 시키려면 전체 행을 삭제하기위한 행 키만 있으면되므로 스캔 결과에 어떤 열 패밀리도 포함시키지 마십시오.

둘째, 디자인에 관한 것입니다. 먼저 요구 사항에 대한 이해는 콘텐츠 id가있는 콘텐츠가 있고 각 콘텐츠에는 차트가 생성되어 해당 데이터가 저장됩니다. 날짜별로 콘텐츠 당 여러 개의 차트가있을 수 있으며 순위에 따라 다릅니다. 또한 마지막으로 생성 된 콘텐츠의 차트가 표의 맨 위에 표시되기를 원합니다.

필자가 가정 할 경우 auto_id, content_charts 및 generated_order의 세 테이블을 사용하는 것이 좋습니다. content_charts에 대한 행 키의 내용 ID는 generated_order에 대한 행 키가 길고 은 자동으로 감소되고HTableInterface API을 사용합니다. 감소 시키려면 '-1'을 앱의 첫 번째 시작시 또는 auto_id 테이블에서 Long.MAX_VALUE 값을 오프셋 및 초기화 할 양으로 사용하십시오. 이제 차트 데이터를 지우려면 delete을 사용하여 열 패밀리를 정리 한 다음 새 데이터를 다시 입력 한 다음 generated_order 테이블에 넣으십시오. 이 방법으로 최신 삽입은 컨텐츠 ID를 셀 값으로 유지하는 최신 삽입 테이블의 맨 위에 있습니다. generated_order에 내용 당 하나의 항목 만 있는지 확인하려면 generated_order id를 먼저 저장하고 값을 가져 와서 열을 넣을 때 content_charts에 저장하고 열 패밀리를 삭제하기 전에 먼저 generated_order에서 행을 삭제하십시오. 이 방법을 사용하면 최대 2 회의 조회를 사용하여 차트를 검색하고 차트를 검색 할 필요가 없으며 콘텐츠를 조회하고 차트 할 수 있습니다.

도움이되기를 바랍니다.

2

관련 범위 (시작 행, 끝 행, 필터)를 정의하는 검색을 사용하는 BulkDeleteProtocol을 사용할 수 있습니다.

내가 상황에 달렸다 here

+1

을 원하는이 객체가 (96)에 포함되지 않은 것을 구현하는 내 코드입니다 – Adelin

2

를 참조 이것은 당신이

Scan scan = new Scan(); 
    scan.addFamily("Family"); 
    scan.setStartRow(structuredKeyMaker.key(starDate)); 
    scan.setStopRow(structuredKeyMaker.key(endDate + 1)); 
try { 
    ResultScanner scanner = table.getScanner(scan); 


    Iterator<Entity> cdrIterator = new EntityIteratorWrapper(scanner.iterator(), EntityMapper.create(); // this is a simple iterator that maps rows to exact entity of mine, not so important ! 

    List<Delete> deletes = new ArrayList<Delete>(); 
    int bufferSize = 10000000; // this is needed so I don't run out of memory as I have a huge amount of data ! so this is a simple in memory buffer 
    int counter = 0; 
    while (entityIterator.hasNext()) { 
     if (counter < bufferSize) { 
          // key maker is used to extract key as byte[] from my entity 
      deletes.add(new Delete(KeyMaker.key(entityIterator.next()))); 
      counter++; 

     } else { 
      table.delete(deletes); 
      deletes.clear(); 
      counter = 0; 
     } 
    } 

    if (deletes.size() > 0) { 
     table.delete(deletes); 
     deletes.clear(); 
    } 

} catch (IOException e) { 
    e.printStackTrace(); 
}