2016-09-02 8 views
2

HBaseテーブルで30000万行を削除したいと思います。 HBase APIを使用してDeleteオブジェクトのバッチを送信できます。しかし、私はそれが多くの時間がかかることに恐れています。HBaseバルクを完全バルクロードとして削除

私は数百万行を挿入したいという前のコードの場合でした。 HBase APIを使用しPutsのバッチを送信する代わりに、私は値としてRowKey/Putを発行し、LoadIncrementalHFiles(完全なバルク)で出力を直接書き込むようにHFileOutputFormat2.configureIncrementalLoad(job, table, regionLocator)を使用してReducerを設定しました負荷)。はるかに速かった(3時間ではなく5分間)。

だから私は一括削除するために同じことをしたかった。

しかし、私がKeyValueまたはPut(PutSortReducer)のために減速を設定するには、[削除] HFileOutputFormat2として試行してこの技術を使用することはできませんが、何も削除のために存在していないようです。

私の第一の質問は、「DeleteSortReducer」がDeleteの完全な一括読み込みテクニックを有効にする理由は何ですか?行方不明だけですか?あるいはそれを正当化する深い理由はありますか?

2番目の質問は関連しています.PutSortReducerのコードをコピー/ペーストしてDeleteに適合させ、それを私の仕事のReducerとして渡したらうまくいくのでしょうか? HBaseはバルクロードで完全な墓石であるHFilesを生成するでしょうか?

例:すべての

public class DeleteSortReducer extends 
     Reducer<ImmutableBytesWritable, Delete, ImmutableBytesWritable, KeyValue> { 

    @Override 
    protected void reduce(
      ImmutableBytesWritable row, 
      java.lang.Iterable<Delete> deletes, 
      Reducer<ImmutableBytesWritable, Delete, 
        ImmutableBytesWritable, KeyValue>.Context context) 
      throws java.io.IOException, InterruptedException 
    { 
     // although reduce() is called per-row, handle pathological case 
     long threshold = context.getConfiguration().getLong(
       "putsortreducer.row.threshold", 1L * (1<<30)); 
     Iterator<Delete> iter = deletes.iterator(); 
     while (iter.hasNext()) { 
      TreeSet<KeyValue> map = new TreeSet<KeyValue>(KeyValue.COMPARATOR); 
      long curSize = 0; 
      // stop at the end or the RAM threshold 
      while (iter.hasNext() && curSize < threshold) { 
       Delete d = iter.next(); 
       for (List<Cell> cells: d.getFamilyCellMap().values()) { 
        for (Cell cell: cells) { 
         KeyValue kv = KeyValueUtil.ensureKeyValue(cell); 
         map.add(kv); 
         curSize += kv.heapSize(); 
        } 
       } 
      } 
      context.setStatus("Read " + map.size() + " entries of " + map.getClass() 
        + "(" + StringUtils.humanReadableInt(curSize) + ")"); 
      int index = 0; 
      for (KeyValue kv : map) { 
       context.write(row, kv); 
       if (++index % 100 == 0) 
        context.setStatus("Wrote " + index); 
      } 

      // if we have more entries to process 
      if (iter.hasNext()) { 
       // force flush because we cannot guarantee intra-row sorted order 
       context.write(null, null); 
      } 
     } 
    } 
} 
+0

上記のプログラムの結果はどうですか?他のアプローチを試したことがありますか?もしそうなら、彼らは何ですか? –

答えて

3

まず、操作を削除する方法をいくつかの単語は、HBaseの中で働いています。 deleteコマンドでは、HBaseはデータを削除済みとしてマークし、その情報をHFileに書き込みます。実際には、データはディスクから削除されず、ストレージにはデータと削除マークの2つのレコードが存在します。圧縮後のみ、データはディスクストレージから削除されます。

これらのすべての情報は、KeyValueで表されます。表すデータのKeyValueがKeyValue.Typeで、Putに等しい。削除マークKeyValue.Typeには、次のいずれかの値が設定されます。Delete,DeleteColumn,DeleteFamily,DeleteFamilyVersion

あなたのケースでは、KeyValue.Typeの特別な値を持つKeyValueを作成することによって一括削除を達成することができます。あなたは1列のみを削除したい場合たとえば、あなたは

KeyValue(byte[] row, byte[] family, byte[] qualifier, 
         long timestamp, KeyValue.Type type) 

    //example 

    KeyValue kv = new KeyValeu(row, family, qualifier, 
            time, KeyValue.Type.DeleteColumn) 

あなたは特別なDeleteSortReducerを必要としない最初の質問への答えは、あなたがKeyValueのために減速を設定する必要がありますコンストラクタを使用して、KeyValueを作成する必要があります。 2番目の質問の答えはいいえです。

+0

Mapperは次のようなものを出力すべきですか?byte [] rowkey = ...; KeyValue kv =新しいKeyValue(rowkey、System.currentTimeMillis()、KeyValue.Type.Delete); – Comencau

+1

はい、行全体を削除する場合。 1つの列または列ファミリだけを削除する場合は、DeleteColumn、DeleteFamily修飾子を使用する必要があります。 –

+0

それは動作します。ありがとう。 – Comencau

関連する問題