Hbase快速计算行数

时间:2012-07-07 12:42:49

标签: hadoop hbase bigdata

现在我实现了ResultScanner这样的行计数

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

如果数据达到数百万时计算量很大。我想实时计算我不想使用Mapreduce

如何快速计算行数。

12 个答案:

答案 0 :(得分:95)

在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 :(得分:29)

您可以使用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

答案 2 :(得分:7)

使用HBase附带的HBase rowcount map/reduce job

答案 3 :(得分:6)

如果由于某种原因无法使用RowCounter,那么这两个过滤器的组合应该是获得计数的最佳方式:

FirstKeyOnlyFilter() AND KeyOnlyFilter()

FirstKeyOnlyFilter将导致扫描程序仅返回它找到的第一个列限定符,而不是扫描程序返回表中的所有列限定符,这将最小化网络带宽。如果只选择一个列限定符返回呢?如果您可以保证每行都存在列限定符,那么这将有效,但如果不是这样,那么您将获得不准确的计数。

KeyOnlyFilter将导致扫描程序仅返回列族,并且不会返回列限定符的任何值。这进一步降低了网络带宽,在一般情况下,网络带宽不会占到减少的大部分,但是可能存在边缘情况,其中前一个过滤器选择的第一列恰好是一个非常大的值。 / p>

我尝试使用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提示。

答案 4 :(得分:5)

在HBASE中计算行的简单,有效和高效的方法:

  1. 无论何时插入行触发此API,都会增加该特定单元格。

    Htable.incrementColumnValue(Bytes.toBytes("count"), Bytes.toBytes("details"), Bytes.toBytes("count"), 1);
    
  2. 检查该表中存在的行数。只需对该特定行'计数'使用“获取”或“扫描”API。

  3. 通过使用此方法,您可以在不到一毫秒的时间内获得行计数。

答案 5 :(得分:3)

您可以使用自HBase 0.92以来可用的协处理器。请参阅CoprocessorAggregateProtocol以及example

答案 6 :(得分:3)

要在正确的YARN群集上计算Hbase表记录计数,您还必须设置地图减少作业队列名称:

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

答案 7 :(得分:1)

如果您正在使用扫描仪,请在扫描仪中尽量让它返回最少数量的限定符。实际上,您返回的限定符应该是您可用的最小(以字节大小为单位)。这将极大地加速您的扫描。

不幸的是,这只会到目前为止(数百亿?)。更进一步,您可以实时执行此操作,但首先需要运行mapreduce作业来计算所有行。

将Mapreduce输出存储在HBase的单元格中。每次添加行时,将计数器递增1.每次删除行时,递减计数器。

当您需要实时访问行数时,您会在HBase中读取该字段。

没有快速计算行数的方法,否则就会缩放。你只能算这么快。

答案 8 :(得分:1)

你可以在这里找到示例:

/**
     * 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;
    }

答案 9 :(得分:1)

转到Hbase主目录并运行此命令

./ bin / hbase org.apache.hadoop.hbase.mapreduce.RowCounter'namespace:tablename'

这将启动mapreduce作业,输出将显示hbase表中存在的记录数。

答案 10 :(得分:0)

两种方法为我工作,使用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

答案 11 :(得分:-1)

  

你可以试试hbase api方法!

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