今、私はこのようにResultScanner
の上に行カウントを実装します
for (Result rs = scanner.next(); rs != null; rs = scanner.next()) {
number++;
}
数百万時間の計算に達するデータが大きい場合、Mapreduceを使用したくないリアルタイムで計算したい
行数をすばやくカウントする方法。
HBaseでRowCounterを使用 RowCounterは、テーブルのすべての行をカウントするmapreduceジョブです。これは、メタデータの不一致が懸念される場合に、HBaseがテーブルのすべてのブロックを読み取ることができるように、健全性チェックとして使用するのに適したユーティリティです。 mapreduceはすべて単一のプロセスで実行されますが、MapReduceクラスターを使用して悪用する場合は高速に実行されます。
$ hbase org.Apache.hadoop.hbase.mapreduce.RowCounter <tablename>
Usage: RowCounter [options]
<tablename> [
--starttime=[start]
--endtime=[end]
[--range=[startKey],[endKey]]
[<column1> <column2>...]
]
Hbaseのcountメソッドを使用して、行数をカウントできます。しかし、はい、大きなテーブルの行のカウントは遅くなる可能性があります。count 'tablename' [interval]
戻り値は行数です。
この操作には長い時間がかかる場合があります(「$ HADOOP_HOME/bin/hadoop jar hbase.jar rowcount」を実行して、mapreduceジョブをカウントします)。現在のカウントは、デフォルトで1000行ごとに表示されます。カウント間隔はオプションで指定できます。スキャンキャッシュは、デフォルトでカウントスキャンで有効になっています。デフォルトのキャッシュサイズは10行です。行のサイズが小さい場合は、このパラメーターを増やすことができます。
例:
hbase> count 't1'
hbase> count 't1', INTERVAL => 100000
hbase> count 't1', CACHE => 1000
hbase> count 't1', INTERVAL => 10, CACHE => 1000
同じコマンドをテーブル参照で実行することもできます。テーブル 't1'への参照がある場合、対応するコマンドは次のようになります。
hbase> t.count
hbase> t.count INTERVAL => 100000
hbase> t.count CACHE => 1000
hbase> t.count INTERVAL => 10, CACHE => 1000
何らかの理由でRowCounter
を使用できない場合は、これら2つのフィルターの組み合わせがカウントを取得する最適な方法である必要があります。
FirstKeyOnlyFilter() AND KeyOnlyFilter()
FirstKeyOnlyFilter
は、スキャナーがテーブル内のすべての列修飾子を返すのに対して、スキャナーが検出した最初の列修飾子のみを返すようにします。これにより、ネットワーク帯域幅が最小化されます。返す列修飾子を1つだけ選択するのはどうですか?これは、列修飾子がすべての行に存在することを保証できれば機能しますが、そうでない場合は、不正確なカウントを取得します。
KeyOnlyFilter
を使用すると、スキャナーは列ファミリーのみを返し、列修飾子には値を返しません。これにより、ネットワーク帯域幅がさらに削減されますが、これは一般的な場合ではあまり削減されませんが、前のフィルターで選択された最初の列が非常に大きな値になるエッジの場合があります。
scan.setCaching
で遊んでみましたが、結果はいたるところにありました。おそらくそれが役立つかもしれません。
開始と停止の間に1600万行あり、次の疑似経験的テストを行いました。
FirstKeyOnlyFilterとKeyOnlyFilterを有効にした場合: キャッシングが設定されていない場合(つまり、デフォルト値)、188秒かかりました。 キャッシングを1に設定した場合、 188秒かかりました キャッシングを10に設定した場合、200秒かかりました キャッシングを100に設定した場合、187秒かかりました キャッシングを1000に設定した場合、183秒かかりました。 キャッシングを10000に設定すると、199秒かかりました。 キャッシングを100000に設定すると、199秒かかりました。 FirstKeyOnlyFilterとKeyOnlyFilterを無効にした場合: キャッシュが設定されていない場合(つまり、デフォルト値)、309秒かかりました
私はこれについて適切なテストを行うことを気にしませんでしたが、FirstKeyOnlyFilter
とKeyOnlyFilter
が良いことは明らかです。
さらに、この特定のテーブルのセルは非常に小さいため、別のテーブルではフィルターがさらに優れていたと思います。
Javaコードサンプル:
import Java.io.IOException; import org.Apache.hadoop.conf.Configuration; import org.Apache.hadoop.hbase.HBaseConfiguration; import org.Apache.hadoop.hbase.client.HTable; import org.Apache.hadoop.hbase.client.Result; import org.Apache.hadoop.hbase.client .ResultScanner; import org.Apache.hadoop.hbase.client.Scan; import org.Apache.hadoop.hbase.util.Bytes; import org.Apache.hadoop.hbase.filter.RowFilter; import org.Apache.hadoop.hbase.filter.KeyOnlyFilter; import org.Apache.hadoop.hbase.filter.FirstKeyOnlyFilter; import org.Apache.hadoop.hbase.filter.FilterList; import org.Apache.hadoop.hbase.filter.CompareFilter.CompareOp; import org .Apache.hadoop.hbase.filter.RegexStringComparator; public class HBaseCount { public static void main(String [] args)throws IOException { Configuration config = HBaseConfiguration.create(); HTableテーブル= new HTable(config、 "my_table"); Scan scan = new Scan( Bytes.toBytes( "foo")、Bytes .toBytes( "foo〜") ); if(args.length == 1){ scan.setCaching(Integer.valueOf(args [ 0])); } System.out.println( "スキャンのキャッシングは" + scan.getCaching()); FilterList allFilters = new FilterList (); allFilters.addFilter(new FirstKeyOnlyFilter()); allFilters.addFilter(new KeyOnlyFilter()); scan.setFilter(allFilters); ResultScanner scanner = table.getScanner(scan); int count = 0; long start = System。 currentTimeMillis(); [.__ __。] { for(Result rr = scanner.next(); rr!= null; rr = scanner.next()){ count + = 1; if(count%100000 == 0)System.out.println(count); } }最後に{ scanner.close(); } long end = System.currentTimeMillis(); longlapseTime = end-start; System.out.println( "経過時間は" +(elapsedTime/1000F)); } }
pychbase のコードサンプルは次のとおりです。
from pychbase import Connection c = Connection() t = c.table( 'my_table') #内部では、これはFirstKeyOnlyFilterとKeyOnlyFilter #以下のhappybaseの例に似ています print t.count(row_prefix = "foo")
Happybaseのコードサンプルは次のとおりです。
from happybase import Connection c = Connection(...) t = c.table( 'my_table') count = 0 _ for t.scan(filter = 'FirstKeyOnlyFilter()AND KeyOnlyFilter()'): count + = 1 print count
@ Tuckrおよび@KennyCason に感謝します。
HBase rowcount map/reduce job を使用します。これはHBaseに含まれています
HBASEで行をカウントするシンプルで効果的かつ効率的な方法:
行を挿入するたびに、特定のセルをインクリメントするこのAPIをトリガーします。
Htable.incrementColumnValue(Bytes.toBytes("count"), Bytes.toBytes("details"), Bytes.toBytes("count"), 1);
そのテーブルに存在する行の数を確認します。特定の行の「カウント」に対して「取得」または「スキャン」APIを使用するだけです。
このメソッドを使用すると、1秒未満で行カウントを取得できます。
HBase 0.92以降で利用可能なコプロセッサを使用できます。 コプロセッサ および AggregateProtocol および 例 を参照してください
適切なYARNクラスターでHbaseテーブルのレコードカウントをカウントするには、map reduceジョブキュー名も設定する必要があります。
hbase org.Apache.hadoop.hbase.mapreduce.RowCounter -Dmapreduce.job.queuename= < Your Q Name which you have SUBMIT access>
< TABLE_NAME>
スキャナーを使用している場合は、スキャナーでできるだけ少ない数の修飾子を返すようにしてください。実際、返される修飾子は、使用可能な限り最小(バイトサイズ)である必要があります。これにより、スキャンが大幅に高速化されます。
幸いなことに、これはこれまでのところ(数百万から10億?)さらに進めるには、これをリアルタイムで実行できますが、最初にmapreduceジョブを実行してすべての行をカウントする必要があります。
Mapreduce出力をHBaseのセルに保存します。行を追加するたびに、カウンターを1ずつ増やします。行を削除するたびに、カウンターを減らします。
行数にリアルタイムでアクセスする必要がある場合、HBaseでそのフィールドを読み取ります。
それ以外の場合は、スケーリングする方法で行をカウントする高速な方法はありません。あなたはとても速く数えることができます。
Hbaseホームディレクトリに移動し、このコマンドを実行します。
./ bin/hbase org.Apache.hadoop.hbase.mapreduce.RowCounter 'namespace:tablename'
これにより、mapreduceジョブが起動され、出力にはhbaseテーブルに存在するレコードの数が表示されます。
Uはここにサンプル例を見つけることができます:
/**
* Used to get the number of rows of the table
* @param tableName
* @param familyNames
* @return the number of rows
* @throws IOException
*/
public long countRows(String tableName, String... familyNames) throws IOException {
long rowCount = 0;
Configuration configuration = connection.getConfiguration();
// Increase RPC timeout, in case of a slow computation
configuration.setLong("hbase.rpc.timeout", 600000);
// Default is 1, set to a higher value for faster scanner.next(..)
configuration.setLong("hbase.client.scanner.caching", 1000);
AggregationClient aggregationClient = new AggregationClient(configuration);
try {
Scan scan = new Scan();
if (familyNames != null && familyNames.length > 0) {
for (String familyName : familyNames) {
scan.addFamily(Bytes.toBytes(familyName));
}
}
rowCount = aggregationClient.rowCount(TableName.valueOf(tableName), new LongColumnInterpreter(), scan);
} catch (Throwable e) {
throw new IOException(e);
}
return rowCount;
}
2つの方法でSpeedを使用してhbaseテーブルから行数を取得しました
シナリオ#1
Hbaseテーブルのサイズが小さい場合、有効なユーザーでhbase Shellにログインして実行します
>count '<tablename>'
例
>count 'employee'
6 row(s) in 0.1110 seconds
シナリオ#2
Hbaseテーブルのサイズが大きい場合、組み込みのRowCounterマップリデュースジョブを実行します。有効なユーザーでhadoopマシンにログインし、実行します。
/$HBASE_HOME/bin/hbase org.Apache.hadoop.hbase.mapreduce.RowCounter '<tablename>'
例:
/$HBASE_HOME/bin/hbase org.Apache.hadoop.hbase.mapreduce.RowCounter 'employee'
....
....
....
Virtual memory (bytes) snapshot=22594633728
Total committed heap usage (bytes)=5093457920
org.Apache.hadoop.hbase.mapreduce.RowCounter$RowCounterMapper$Counters
ROWS=6
File Input Format Counters
Bytes Read=0
File Output Format Counters
Bytes Written=0