Я работаю с большим набором данных, хранящихся в HBase. Многие из значений, хранящихся в моих столбцах, на самом деле являются «векторами» данных - множественными значениями. Я решил установить хранение нескольких значений через ByteBuffer
. Так как я знаю тип данных, хранящихся в каждом столбце в моих семействах столбцов, я написал серию классов, расширяющих базовый класс, который охватывает ByteBuffer
и дает мне простой набор методов для чтения отдельных значений, а также добавления дополнительных значения до конца. Я протестировал этот класс независимо от моего проекта HBase, и он работает, как и ожидалось.
Чтобы обновить мою базу данных (почти каждая строка обновляется в каждом обновлении), я использую задание TableMapper
mapreduce для перебора каждой строки в моей базе данных. Каждый из моих картографов (в моем кластере их шесть) загружает весь файл обновления (редко более 50 МБ) в память, а затем обновляет каждый идентификатор строки при его итерации по нему.
Проблема, с которой я сталкиваюсь , заключается в том, что каждый раз, когда я извлекаю значение данных из объекта Result
, к его концу добавляется 4 байта. Это усложняет мое обновление, потому что я не уверен, стоит ли ожидать, что этот «заполнитель» будет каждый раз лишним 4 байта, или он может вылиться в нечто большее / меньшее. Поскольку я загружаю это в свою оболочку ByteBuffer
, важно, чтобы не было заполнения, потому что это могло бы привести к пробелам в моих данных, когда я добавляю к ним дополнительные точки данных, что сделает невозможным их последующее чтение без ошибка.
Я написал тест, чтобы подтвердить свою гипотезу, создав тестовую таблицу и класс. В таблице имеется только одна точка данных на столбец (одна двойная - я подтвердил, что длина входных байтов равна 8), и я написал следующий код для ее извлечения и проверки.
HTable table = new HTable("test");
byte[] rowId = Bytes.toBytes("myid");
Get get = new Get(rowId);
byte[] columnFamily = Bytes.toBytes("data");
byte[] column = Bytes.toBytes("column");
get.addColumn(columnFamily, column);
Result = table.get(get);
byte[] value = result.value();
System.out.printlin("Value size: " + value.length);
double doubleVal = Bytes.toDouble(value);
System.out.println("Fetch yielded: " + doubleVal);
byte[] test = new byte[8];
for (int i = 0; i < value.length - 4; i++)
blah[i] = value[i];
double dval = Bytes.toDouble(test);
System.out.println("dval: " + dval);
table.close()
Что приводит к:
Value size: 12
Fetch yielded: 0.3652
dval: 0.3652
Эти значения ожидаемые.
Есть мысли о том, как решить эту проблему? Мне известно о существовании механизмов сериализации, таких как Avro, но я стараюсь пока не использовать их, и мои данные настолько просты, что я чувствую, что не должен был это делать.
РЕДАКТИРОВАТЬ: Я продолжил, урезая мои данные по наибольшему общему числу, кратному размеру моего типа данных. По моему опыту, эти дополнительные байты добавляются исключительно в конец моего byte[]
массива. Я сделал несколько классов, которые обрабатывают это автоматически довольно чистым способом, но мне все еще интересно, почему это может происходить.