Если вы не можете использовать 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