2012-07-07 146 views
33

的數量現在我實現行數超過ResultScanner這樣HBase的快速計算行

for (Result rs = scanner.next(); rs != null; rs = scanner.next()) { 
    number++; 
} 

如果數據達到了數以百萬計的時間計算是large.I要計算在,我不希望使用實時Mapreduce

如何快速計算行數。

回答

7

是已經被包含HBase的

+0

我用的行數示例的源代碼,並保存結果在一個變量中,我得到了計數器:'job.getCounters()。findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue();' – Paschalis 2013-02-18 00:59:14

4

簡單,有效的方式在HBASE數行:

  1. 當你插入一行觸發這個API,這將增加該特定細胞。

    Htable.incrementColumnValue(Bytes.toBytes("count"), Bytes.toBytes("details"), Bytes.toBytes("count"), 1); 
    
  2. 檢查該表中存在的行數。只需使用「獲取」或「掃描」API即可查看該特定行的「數量」。

通過使用此方法,您可以在少於一毫秒內獲得行計數。

+1

這是一個好方法。但時間hbase使用增量是hbase放數據的較大時間。 – cldo 2012-11-27 07:35:03

+1

如果該行已存在並更新了該怎麼辦?這可以計算額外的行,對嗎? – Paschalis 2013-02-18 00:43:05

+0

沒有。我想告訴'時間hbase使用增量是更大的時間'。我想跑得更快 – cldo 2013-03-15 17:58:03

1

如果您正在使用掃描儀,請在掃描儀中嘗試儘可能返回最少量的限定符。事實上,你所返回的限定符應該是最小的(以字節大小),因爲你有可用的。這將極大地加快您的掃描速度。

不幸的是,這隻能擴展到目前爲止(數百億?)。要進一步研究,您可以實時執行此操作,但您首先需要運行mapreduce作業來統計所有行。

將Mapreduce輸出存儲在HBase的單元中。每次添加一行時,都將計數器增加1.每次刪除一行時,都會減少計數器。

當您需要實時訪問行數時,您可以在HBase中讀取該字段。

沒有快速的方式來計算行,否則以一種可縮放的方式。你只能計算得這麼快。

+2

事實上,您可以使用'FirstKeyOnlyFilter'來代替「返回儘可能少的限定符」。作爲掃描過濾器 – 2013-07-21 11:46:12

+0

@KennyCason「FirstKeyOnlyFilter」究竟做了什麼?從[thrift docs](我無法理解這個解釋:'[FirstKeyOnlyFilter]只返回每行的第一個鍵值 - 這是否意味着它只是選取第一個單元格並返回該單元格? – 2017-02-19 20:41:23

+0

@KennyCason在測試結束後好了,它會選擇第一個單元格,並返回唯一的單元格。爲什麼你會建議通過@Tucker的建議返回最小限定符?例如,如果FirstKeyOnlyFilter選擇的第一個鍵值具有一個非常大的值,那麼這會減慢掃描的速度;另一方面,如果選擇具有最小值的限定符,但該限定符不會出現在所有要計數的行中,那麼您將獲得一個不準確的計數 – 2017-02-19 20:54:37

75

在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>...] 
    ] 
+1

@cldo,你應該接受這個答案 – WattsInABox 2016-01-28 17:18:45

+1

K,跑這個,在哪裏打印答案? 'org.apache.hadoop.hbase.mapreduce.RowCounter $ RowCounterMapper $ Counters ROWS = 55438' < - 那它? – samthebest 2016-02-15 15:37:16

22

您可以使用hbase中的count方法來計算行數。但是,是的,計算一個大表的行可以是slow.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 
+7

該計數器運行速度很慢,只能從hbase shell訪問。對於大表不推薦使用。 – articuno 2015-06-02 13:44:55

+0

@articuno確切地 – 2017-02-06 08:59:22

-1

你可以試試HBase的API方法!

org.apache.hadoop.hbase.client.coprocessor.AggregationClient

+0

您能否爲您的答案提供更多的上下文以及一些相關文檔的鏈接? – Suever 2016-02-13 03:11:26

1

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; 
    } 
+0

有沒有辦法證明'configuration.setLong(「hbase.client.scanner。緩存「,1000);'工作?例如,如果我設置它,並且稍後調用'scanner.getCaching()',它將返回'-1'。 – 2017-02-20 03:28:27

5

如果你不能不管出於什麼原因,然後結合使用RowCounter這兩個過濾器應該是獲得計數的最佳方式:

FirstKeyOnlyFilter() AND KeyOnlyFilter() 

FirstKeyOnlyFilter將導致僅掃描器返回第一柱限定符它發現,相對於掃描儀返回所有在表中的列限定符,這將最小化網絡帶寬的。簡單地選擇一個列限定符返回?這將工作,如果你能機制保障該列資格賽存在的每一行,但如果這是不正確的,那麼你會得到一個不準確的計數。

KeyOnlyFilter將導致掃描儀只能返回列族,並且不會對列預選賽返回任何值。這進一步降低了網絡帶寬,在一般情況下,這並不會大幅減少,但是可能會出現邊緣情況,其中前一個過濾器挑選的第一列恰好是一個非常大的值。

我試着玩scan.setCaching,但結果全是這個地方。也許它可以幫助。

我在開始之間有1600萬行,停止我做了以下僞實證檢驗:

 
With FirstKeyOnlyFilter and KeyOnlyFilter activated: 

    With caching not set (i.e., the default value), it took 188 seconds. 
    With caching set to 1, it took 188 seconds 
    With caching set to 10, it took 200 seconds 
    With caching set to 100, it took 187 seconds 
    With caching set to 1000, it took 183 seconds. 
    With caching set to 10000, it took 199 seconds. 
    With caching set to 100000, it took 199 seconds. 

With FirstKeyOnlyFilter and KeyOnlyFilter disabled: 

    With caching not set, (i.e., the default value), it took 309 seconds 

我也懶得做這個適當的測試,但它似乎很清楚的是, FirstKeyOnlyFilterKeyOnlyFilter都不錯。

此外,這個特定表格中的單元格非常小 - 所以我認爲過濾器在不同的表格上會更好。


這裏是一個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 table = 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's caching is " + 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(); 

     try { 
      for (Result rr = scanner.next(); rr != null; rr = scanner.next()) { 
       count += 1; 
       if (count % 100000 == 0) System.out.println(count); 
      } 
     } finally { 
      scanner.close(); 
     } 

     long end = System.currentTimeMillis(); 

     long elapsedTime = end - start; 

     System.out.println("Elapsed time was " + (elapsedTime/1000F)); 

    } 
} 


這裏是一個pychbase代碼示例:

 
    from pychbase import Connection 
    c = Connection() 
    t = c.table('my_table') 
    # Under the hood this applies the FirstKeyOnlyFilter and KeyOnlyFilter 
    # similar to the happybase example below 
    print t.count(row_prefix="foo") 

這裏是一個Happybase代碼示例:

 
    from happybase import Connection 
    c = Connection(...) 
    t = c.table('my_table') 
    count = 0 
    for _ in t.scan(filter='FirstKeyOnlyFilter() AND KeyOnlyFilter()'): 
     count += 1 

    print count 

由於@Tuckr and @KennyCason的小費。

0

轉到HBase的主目錄,並運行此命令,

./bin/hbase org.apache.hadoop.hbase.mapreduce.RowCounter '命名空間:表名'

這將啓動的MapReduce作業,輸出將顯示hbase表中存在的記錄數。

2

要計算一個適當的紗線集羣上的HBase表的記錄數,您必須將地圖縮小作業隊列名稱,以及:

hbase org.apache.hadoop.hbase.mapreduce.RowCounter -Dmapreduce.job.queuename= < Your Q Name which you have SUBMIT access> 
< TABLE_NAME>