HBaseで複数の行を削除する効率的な方法
質問
HBaseで複数の行を削除する効率的な方法はありますか、それとも私のユースケースはHBaseに適していないように臭いがしますか?
チャートにあるアイテムを含む「チャート」という表があります。行キーは次の形式です。chart|date_reversed|ranked_attribute_value_reversed|content_id
特定の日付でチャートを再生したい場合があるため、「chart | date_reversed_1」から「chart | date_reversed_2」までのすべての行を削除したいと思います。スキャンで見つかった各行の削除を発行するよりも良い方法はありますか?削除されるすべての行は互いに近くになります。
1つのアイテム(1つのContent_id)が、ランクreced_attribute_valueが変更された場合に1つのアイテム(1つのContent_id)にある複数のエントリを持たせたくないため、行を削除する必要があります(その変更がチャートを再生する必要がある理由です)。
HBaseの初心者であるので、おそらく私は列の方が良いものを誤用しているかもしれません。デザインの提案があれば、クールです!または、チャートはファイルでより適切に生成される可能性があります(たとえば、出力のHBaseはありません)? MapReduceを使用しています。
解決
まず、範囲の削除ポイントに来ると、hbase、afaikにはまだ範囲削除がありません。しかし、一度に複数の行を削除する方法があります HtableInterface API. 。これについては、単にスキャンから行キーを含む削除オブジェクトを形成し、それらをリストに入れてAPIを使用して完了します!スキャンを高速にするには、スキャン結果に列ファミリを含めないでください。必要なのは行全体を削除するための行キーだけです。
第二に、デザインについて。まず、要件についての私の理解は、コンテンツIDのコンテンツがあり、各コンテンツにはそれらに対して生成されたチャートがあり、それらのデータは保存されます。日付を介してコンテンツごとに複数のチャートがあり、ランクに依存します。さらに、最後に生成されたコンテンツのチャートをテーブルの上部に表示する必要があります。
要件を仮定するために、Auto_ID、content_charts、generated_orderの3つのテーブルを使用することをお勧めします。 content_chartsの行キーはそのコンテンツIDであり、generated_orderの行キーは長いです。 自動決定 使用 HtableInterface API. 。使用量をオフセットして初期化する量として '-1'を減少させるために、アプリの最初の起動時または手動でのauto_idテーブルのmax_valueを初期化します。チャートデータを削除したい場合は、列ファミリを使用して列のファミリを清掃するだけです 消去 次に、新しいデータを元に戻し、Generated_orderテーブルに入れます。このようにして、最新の挿入は、コンテンツIDをセル値として保持する最新の挿入テーブルの上部にもなります。 generated_orderにコンテンツごとに1つのエントリのみがあることを確認する場合は、最初にgenerated_order idを保存し、値を取得し、content_chartsに保存して、列ファミリを削除する前に、最初にgenerated_orderから行を削除します。これにより、2を使用してコンテンツを検索してチャートを作成でき、チャートにはスキャンは必要ありません。
これが役立つことを願っています。
他のヒント
関連する範囲を定義するスキャンを使用するBulkDeleteProtocolを使用できます(開始行、エンドロー、フィルター)。
見る ここ
私はあなたの状況に出くわしました、そしてこれはあなたが望むものを実装する私のコードです
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();
}