Фильтр HBase на ключе массива StructRowKey byte[]

Фильтр HBase по части ключа строки

Это моя таблица (Key — это byte[] с использованием StructRowKeyBuilder с FixedLengthByteWritable для «a», IntWritable для идентификатора и LongWritable для метки времени и содержит в основном всю информацию, значение — это просто счетчик) Ключ состоит из идентификатора (a или p), идентификатор переменной длины, дата со временем в секундах и несколько других идентификаторов после этого (о которых мне все равно, так как я хочу фильтровать по времени).

KEY                             VALUE
a 13  2018-01-01T10:00:00 ...   1
a 13  2018-01-02T11:00:00 ...   1
a 13  2018-01-03T12:00:00 ...   1
a 13  2018-01-04T13:00:00 ...   1
a 15  2018-01-01T10:00:00 ...   1
a 15  2018-01-02T11:00:00 ...   1
a 15  2018-01-03T12:00:00 ...   1
a 123 2018-01-01T10:00:00 ...   1
a 123 2018-01-02T11:00:00 ...   1
a 123 2018-01-03T12:00:00 ...   1
a 123 2018-01-04T10:00:00 ...   1
...
p 13  2018-01-01T10:00:00 ...   1
p 13  2018-01-02T10:00:00 ...   1
p 13  2018-01-03T10:00:00 ...   1
p 666 2018-01-01T10:00:00 ...   1
...

Я хочу получить все данные за определенный период времени, скажем, между 2018-01-01T10:00:00 и 2018-01-02T12:00:00 для всех a.

Итак, я попытался настроить сканирование в начале и конце строки.

StartRow    **a 0 2018-01-01T10:00:00** 
EndRow      **a Integer.MAX_VALUE 2018-01-02T:12:00:01 (+1 second to make it inclusive)**

Это не дало мне правильного результата, так как включало все, что находится между двумя ключами. Так что запись

КЛЮЧ ЗНАЧЕНИЕ a 13 2018-01-04T13:00:00 ... 1

тоже был включен. (Что имеет смысл)

Установка начальной строки на a 0 и конечной строки на целое число. MaxValue ограничивает количество возвращаемых строк до as.

Как мне фильтровать эти строки на стороне сервера с помощью фильтров HBase? Поскольку ключи сериализуются в byte[], у меня нет четкого представления о том, как добиться этого с помощью фильтров.

Любой, кто мог бы указать мне в правильном направлении? (или еще лучше предоставить пример кода в java)

Некоторый код (который, к сожалению, не работает так, как я хочу):

...
byte[] fromKey = Bytes.toBytes("a" + 0);
byte[] toKey = Bytes.toBytes("a" + Integer.MAX_VALUE);
Scan scan = new Scan(fromKey, toKey);

int minId = 0;
int maxId = Integer.MAX_VALUE;
final byte[] fromBytes = Bytes.toBytes("a" + minId + dateFromInMillis);
final BinaryPrefixComparator fromBinaryPrefixComparator = new BinaryPrefixComparator(fromBytes);
final Filter fromFilter = new RowFilter(CompareOp.GREATER_OR_EQUAL, fromBinaryPrefixComparator);

final byte[] toBytes = Bytes.toBytes("a" + maxId + dateFromInMillis);
final BinaryPrefixComparator toBinaryPrefixComparator = new BinaryPrefixComparator(toBytes);
final Filter toFilter = new RowFilter(CompareOp.LESS_OR_EQUAL, toBinaryPrefixComparator);

FilterList filterList= new FilterList(FilterList.Operator.MUST_PASS_ALL, fromFilter, toFilter);

scan.setFilter(filterList);
scanner = myTable.getScanner(scan);
...

person El Shotodore    schedule 10.09.2018    source источник
comment
Можете ли вы добавить подробности о StructRowKeyBuilder, я думаю, это может быть причиной того, как ваши результаты?   -  person mbaxi    schedule 10.09.2018
comment
Я не совсем уверен, как добавить подробности для этого, так как это, кажется, что-то встроенное в protobuf/hbase. Тем временем я обошел проблему, отправив несколько запросов и собрав данные. По сути - получить два списка идентификаторов (для префикса a и p), кэшировать их, а затем выполнить пару сканирований на основе ‹a|b›‹id›dateFrom - dateTo и объединить результаты. Поскольку это просто используется время от времени и не является производственным инструментом, а не для отладки и анализа.   -  person El Shotodore    schedule 06.11.2018


Ответы (1)


Я пытался эмулировать вашу проблему с помощью Phoenix, я не уверен, как StructRowKeyBuilder создает и сохраняет ключ, но если вы реализуете то же самое, используя ключ HBase с разделителями или используя составной Phoenix, вы сможете получить правильные результаты.

Вот что я сделал -

// Create table    
create table stackoverflow (
    id1 char(1) not null,
    id2 integer not null,
    eventdate Date not null,
    id3 varchar not null,
    id4 varchar not null,
    myvalue integer
    CONSTRAINT my_pk PRIMARY KEY (id1, id2, eventdate,id3, id4));

// add data
UPSERT INTO stackoverflow (id1, id2, eventdate,id3, id4, myvalue) VALUES('a', 13, '2018-01-01T10:00:00', 'dummy1', 'dummy2', 1);
.
.
.
UPSERT INTO stackoverflow (id1, id2, eventdate,id3, id4, myvalue) VALUES('p', 13, '2018-01-03T12:00:00', 'dummy1', 'dummy2', 1);
UPSERT INTO stackoverflow (id1, id2, eventdate,id3, id4, myvalue) VALUES('p', 666, '2018-01-01T10:00:00', 'dummy1', 'dummy2', 1);

Далее создан следующий запрос -

select  * from stackoverflow where id1='a' and id2 between 0 and 2147483647 and eventdate between TO_DATE('2018-01-01T10:00:00') and TO_DATE('2018-01-02T12:00:01');

Вот мои результаты, я могу добиться того же, используя HBase java API, но в моем случае сгенерированный составной ключ представляет собой конкатенированную строку, разделенную разделителем «0». Мне кажется, что StructRowKeyBuilder что-то меняет, потому что то, чего вы пытаетесь достичь, - это очень обычный сценарий использования.

a    13   2018-01-01 10:00:00.000  dummy1  dummy2  1        
a    13   2018-01-02 11:00:00.000  dummy1  dummy2  1        
a    15   2018-01-01 10:00:00.000  dummy1  dummy2  1        
a    15   2018-01-02 11:00:00.000  dummy1  dummy2  1        
a    123  2018-01-01 10:00:00.000  dummy1  dummy2  1        
a    123  2018-01-02 11:00:00.000  dummy1  dummy2  1        

Надеюсь это поможет.

person mbaxi    schedule 10.09.2018