Hbase быстро подсчитывает количество строк

Прямо сейчас я реализую подсчет строк по ResultScanner вот так

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

Если данные достигают миллионов вычислений, время вычислений велико. Я хочу вычислять в реальном времени, что я не хочу использовать Mapreduce

Как быстро посчитать количество строк.


person cldo    schedule 07.07.2012    source источник


Ответы (12)


Использование RowCounter в HBase 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>...]
    ]
person Basil Saju    schedule 14.02.2013
comment
K, запустил это, где он печатает ответ? org.apache.hadoop.hbase.mapreduce.RowCounter$RowCounterMapper$Counters ROWS=55438 ‹- что это? - person samthebest; 15.02.2016
comment
HBase count 'имя таблицы' работает очень медленно. Улей и Свинья быстрее. Но этот ответ лучший с точки зрения скорости! - person Paras; 11.04.2019

Вы можете использовать метод count в hbase для подсчета количества строк. Но да, подсчет строк в большой таблице может быть медленным.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
person Coder123    schedule 06.08.2014
comment
Этот счетчик работает очень медленно и доступен только из оболочки hbase. Для больших таблиц не рекомендуется использовать. - person articuno; 02.06.2015
comment
@articuno точно - person jack AKA karthik; 06.02.2017

Если вы не можете использовать RowCounter по какой-либо причине, то комбинация этих двух фильтров должна быть оптимальным способом получения подсчета:

FirstKeyOnlyFilter() AND KeyOnlyFilter()

FirstKeyOnlyFilter приведет к тому, что сканер вернет только первый квалификатор столбца, который он найдет, в отличие от сканера, возвращающего все квалификаторы столбцов в таблице, что минимизирует пропускную способность сети. Как насчет того, чтобы просто выбрать один квалификатор столбца для возврата? Это сработало бы, если бы вы могли гарантировать, что квалификатор столбца существует для каждой строки, но если это не так, вы получите неточный счет.

KeyOnlyFilter приведет к тому, что сканер вернет только семейство столбцов и не вернет никакого значения для квалификатора столбца. Это еще больше снижает пропускную способность сети, что в общем случае не приводит к значительному сокращению, но может быть пограничный случай, когда первый столбец, выбранный предыдущим фильтром, просто оказывается чрезвычайно большим значением.

Я пробовал играть с scan.setCaching, но результаты были повсюду. Возможно, это могло бы помочь.

У меня было 16 миллионов строк между запуском и остановкой, и я провел следующее псевдоэмпирическое тестирование:

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

Я не удосужился провести надлежащее тестирование, но кажется очевидным, что 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 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 и @KennyCason за подсказку.

person Matthew Moisen    schedule 19.02.2017

Используйте задание HBase rowcount map/reduce, включенное в HBase.

person Arnon Rotem-Gal-Oz    schedule 07.07.2012
comment
Я использовал исходный код для примера rowcount, и чтобы сохранить результат в переменной, я получил счетчик, используя: job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue(); - person Paschalis; 18.02.2013

Простой, эффективный и действенный способ подсчета строк в HBASE:

  1. Всякий раз, когда вы вставляете строку, запускайте этот API, который увеличивает эту конкретную ячейку.

    Htable.incrementColumnValue(Bytes.toBytes("count"), Bytes.toBytes("details"), Bytes.toBytes("count"), 1);
    
  2. Чтобы проверить количество строк, присутствующих в этой таблице. Просто используйте «Получить» или «сканировать» API для этого конкретного «количества» строк.

Используя этот метод, вы можете получить количество строк менее чем за миллисекунду.

person Balaji    schedule 16.07.2012
comment
это хороший способ. Но время приращения использования hbase больше, чем время, в которое hbase помещает данные. - person cldo; 27.11.2012
comment
что, если строка уже существует и она обновлена? это может считать дополнительные строки, верно? - person Paschalis; 18.02.2013
comment
нет. Я хочу сказать, что «приращение времени использования hbase больше времени». Я хочу бежать быстрее - person cldo; 15.03.2013
comment
А что делать, если загрузка данных не через hbase API, как у массовой загрузки - person Afshin Moazami; 02.10.2015

Чтобы подсчитать количество записей таблицы Hbase в правильном кластере YARN, вы также должны установить карту, уменьшающую имя очереди заданий:

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

Вы можете использовать сопроцессор, который доступен начиная с HBase 0.92. См. Сопроцессор и AggregateProtocol и пример

person Alexander Kuznetsov    schedule 07.07.2012
comment
У меня это сработало, просто подсчет команды «myTable», спасибо :) - person Abdelali AHBIB; 25.07.2014

Два способа помогли мне получить количество строк из таблицы hbase с помощью Speed

Сценарий 1

Если размер таблицы hbase невелик, войдите в оболочку hbase с действительным пользователем и выполните

>count '<tablename>'

Пример

>count 'employee'

6 row(s) in 0.1110 seconds

Сценарий 2

Если размер таблицы hbase велик, выполните встроенную задачу уменьшения карты RowCounter: войдите в систему с действительным пользователем и выполните:

/$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
person Harsimranjit Singh Kler    schedule 02.01.2019

Если вы используете сканер, постарайтесь, чтобы он возвращал как можно меньше квалификаторов. На самом деле, квалификаторы, которые вы возвращаете, должны быть наименьшими (по размеру байта) из тех, что у вас есть. Это значительно ускорит сканирование.

К сожалению, это пока только масштабируется (миллионы-миллиарды?). Чтобы продвинуться дальше, вы можете сделать это в режиме реального времени, но сначала вам нужно запустить задание mapreduce для подсчета всех строк.

Сохраните выходные данные Mapreduce в ячейке HBase. Каждый раз, когда вы добавляете строку, увеличивайте счетчик на 1. Каждый раз, когда вы удаляете строку, уменьшайте счетчик.

Когда вам нужно получить доступ к количеству строк в режиме реального времени, вы читаете это поле в HBase.

В противном случае нет быстрого способа подсчета строк таким образом, чтобы он масштабировался. Вы можете только считать так быстро.

person Tucker    schedule 17.07.2012
comment
На самом деле вместо того, чтобы возвращать как можно меньше квалификаторов, вы должны использовать FirstKeyOnlyFilter. как фильтр сканирования - person Kenny Cason; 21.07.2013
comment
@KennyCason Что именно делает FirstKeyOnlyFilter? Из [thrift docs]( я не мог понять это объяснение: [FirstKeyOnlyFilter] returns only the first key-value from each row -- Значит ли это, что он просто выбирает первую ячейку и возвращает ее? - person Matthew Moisen; 19.02.2017
comment
@KennyCason Хорошо, после тестирования кажется, что вы выбираете первую ячейку и возвращаете только ее. Почему вы предложили бы это вместо предложения @Tucker вернуть наименьший квалификатор? Например, если первое значение ключа, выбранное FirstKeyOnlyFilter, имеет действительно большое значение, это замедлит сканирование. С другой стороны, если вы выберете квалификатор с наименьшим значением, но этот квалификатор не появится во всех строках, которые вы хотите подсчитать, вы получите неточный подсчет. - person Matthew Moisen; 19.02.2017
comment
@KennyCason Хорошо, я нашел это: используйте FirstKeyOnlyFilter() AND KeyOnlyFilter(). KeyOnlyFilter предотвратит передачу значения столбца по сети. - person Matthew Moisen; 20.02.2017

Вы можете найти образец примера здесь:

/**
     * 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;
    }
person Ranga Reddy    schedule 28.12.2016
comment
Есть ли способ доказать, что configuration.setLong("hbase.client.scanner.caching", 1000); работает? Например, если я установлю его, а позже вызову scanner.getCaching(), он вернет -1. - person Matthew Moisen; 20.02.2017
comment
AggregationClient был удален из hbase 3.1.0. - person aprodan; 25.03.2019

Перейдите в домашний каталог Hbase и выполните эту команду,

./bin/hbase org.apache.hadoop.hbase.mapreduce.RowCounter 'пространство имен:имя_таблицы'

Это запустит задание mapreduce, и на выходе будет показано количество записей, существующих в таблице hbase.

person jack AKA karthik    schedule 06.07.2017

Вы можете попробовать методы hbase api!

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

person draw    schedule 03.02.2016
comment
Не могли бы вы предоставить немного больше контекста для вашего ответа, а также несколько ссылок на соответствующую документацию? - person Suever; 13.02.2016
comment
AggregationClient недоступен в hbase 3.1.0 - person aprodan; 25.03.2019