SingleColumnValueFilter не возвращает правильное количество строк

В нашей таблице HBase каждая строка имеет столбец с именем идентификатор обхода. Используя задание MapReduce, мы хотим обрабатывать в любой момент только строки из данного обхода. Чтобы выполнить задание более эффективно, мы снабдили наш объект сканирования фильтром, который (как мы надеялись) удалит все строки, кроме строк с заданным идентификатором обхода. Однако мы быстро обнаружили, что наши задания не обрабатывали правильное количество строк.

Я написал тестовый сопоставитель, чтобы просто подсчитать количество строк с правильным идентификатором обхода без каких-либо фильтров. Он перебрал все строки в таблице и подсчитал правильное ожидаемое количество строк (~ 15000). Когда мы взяли ту же работу, добавили фильтр к объекту сканирования, счет упал до ~ 3000. Не было никаких манипуляций с самой таблицей во время или между этими двумя заданиями.

Поскольку добавление фильтра сканирования привело к столь резкому изменению видимых строк, мы ожидаем, что просто неправильно построили фильтр.

В нашем задании MapReduce есть один картограф:

public static class RowCountMapper extends TableMapper<ImmutableBytesWritable, Put>{

    public String crawlIdentifier;

    // counters
    private static enum CountRows {
        ROWS_WITH_MATCHED_CRAWL_IDENTIFIER
    }

    @Override
    public void setup(Context context){
        Configuration configuration=context.getConfiguration();
        crawlIdentifier=configuration.get(ConfigPropertyLib.CRAWL_IDENTIFIER_PROPERTY);

    }

    @Override
    public void map(ImmutableBytesWritable legacykey, Result row, Context context){
        String rowIdentifier=HBaseSchema.getValueFromRow(row, HBaseSchema.CRAWL_IDENTIFIER_COLUMN);
        if (StringUtils.equals(crawlIdentifier, rowIdentifier)){
            context.getCounter(CountRows.ROWS_WITH_MATCHED_CRAWL_IDENTIFIER).increment(1l);
        }
    }
}

Настройка фильтра такая:

String crawlIdentifier=configuration.get(ConfigPropertyLib.CRAWL_IDENTIFIER_PROPERTY);
if (StringUtils.isBlank(crawlIdentifier)){
    throw new IllegalArgumentException("Crawl Identifier not set.");
}

// build an HBase scanner
Scan scan=new Scan();
SingleColumnValueFilter filter=new SingleColumnValueFilter(HBaseSchema.CRAWL_IDENTIFIER_COLUMN.getFamily(),
    HBaseSchema.CRAWL_IDENTIFIER_COLUMN.getQualifier(),
    CompareOp.EQUAL,
    Bytes.toBytes(crawlIdentifier));
filter.setFilterIfMissing(true);
scan.setFilter(filter);

Мы используем неправильный фильтр или неправильно его настроили?

РЕДАКТИРОВАТЬ: мы рассматриваем ручное добавление всех семейств столбцов в соответствии с https://issues.apache.org/jira/browse/HBASE-2198, но я уверен, что сканирование включает все семейства по умолчанию.


person whiterook6    schedule 07.06.2012    source источник
comment
Можете еще показать исходный маппер, в котором вручную делали фильтрацию?   -  person Hari Menon    schedule 07.06.2012
comment
Это был тот же картограф; единственная разница в том, что я не назначал фильтр объекту сканирования (во втором блоке кода). Конечно, то, что вы называете ручной фильтрацией, — это просто блок if() в методе map().   -  person whiterook6    schedule 08.06.2012
comment
@whiterook6, ты когда-нибудь решал эту проблему? Спасибо   -  person hba    schedule 24.01.2014
comment
Извините, понятия не имею. Это было почти два года назад; Я не могу вспомнить.   -  person whiterook6    schedule 24.01.2014


Ответы (1)


Фильтр выглядит правильно, но при определенных условиях один сценарий, который может вызвать это, связан с кодировкой символов. Ваш фильтр использует Bytes.toBytes(String), который использует UTF8 [1], тогда как вы можете использовать собственную кодировку символов в HBaseSchema или при записи записи, если вы используете String.getBytes()[2 ]. Убедитесь, что CrawlIdentifier изначально был записан в HBase, используя следующее, чтобы убедиться, что фильтр сравнивает подобное в отфильтрованном сканировании.

Bytes.toBytes(crawlIdentifier)

[1] http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html#toBytes(java.lang.String) [2] http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#getBytes()

person timrobertson100    schedule 08.06.2012
comment
Некоторое время назад мы нашли ошибку, связанную с этой самой проблемой. Мы сожгли код, ища String.toBytes(), и заменили их все. Код для записи идентификатора обхода был написан правильно. - person whiterook6; 08.06.2012