Низкоуровневый столбчатый механизм хранения с Java API

Не могли бы вы предложить низкоуровневый столбчатый механизм хранения, который можно интегрировать в Java-приложение?

Причина: нам нужен столбчатый механизм хранения с Java API, чтобы интегрировать его в наше приложение для обработки данных.

Справочная информация: необработанные данные поступают из различных файлов CSV/TSV/WtfSV размером до 10 ГБ (в большинстве случаев значительно меньше). Приложение имеет предопределенный набор настраиваемых операций для очистки / преобразования / проверки данных (аналогично OpenRefine || DataWrangler || DataCleaner)

Проблема: сейчас мы используем H2 MVStore со значениями Object[] в виде строк, очевидно, он хранится как одна запись, поэтому вся строка десериализуется каждый раз, когда нам нужно обработать только один столбец.

Требования:

  1. Добавление / удаление столбца в любое время
  2. Основные классы значений Java (String, Numbers, Date), поддерживаемые из коробки
  3. Операция Get by index / Итерация, начиная с
  4. Файловое хранилище (по соображениям производительности)
  5. Было бы хорошо иметь возможность управления версиями данных в столбце (или даже в строке столбца).

Пример API, который нам нужен:

DataSet dataSet = Storage.dataSet('SomeName').withFilePath('C:\data\somename.dat').open(); //Open or create if not exists

//class DataSet implements List<Column>
//class Column implements List<T>
Column<String> col1 = dataSet.column('Col1').withType(String.class) //Column automatically created if not exists (only after user try to add data)
Column<Integer> col2 = dataSet.column('Col2').withType(Integer.class)

//Load data into column
for(String s : someStringList){
  long idx = col1.add(s)
}

//Low priority one
Column col3 = dataSet.column('Col3').withCustomMapper(SomeClass.class, 
  new Mapper {
    //byte[] can be InputStream, DataInputStream, etc... it does not matter
    public SomeClass read(byte[] data){ /*some logic*/}
    public byte[] write(SomeClass data){ /*some logic*/} 
})

//Add entire row. Typechecking at runtime would be ok
long idx = dataSet.addRow(["123", 321, new SomeClass()]); 

//Get by index
SomeClass foo = dataSet.column("Col1", SomeClass.class).get(idx)

//Iterator from index
Iterator<String> it = col1.iterator(startIndex)

/*
Iterator with parallel prefetching
This iterator dynamically adjusts read-ahead buffer in a way 
that provides max performance for single threaded iterator,
eg there is no need to run multiple deserializing threads 
if iterator itself is slow.
*/
PrefetchingIterator<DataRow> it3 = dataSet.iterator(startIndex).withMaxPerformanceParallelPrefetcher()

//Not required function, but it would be good if it is exists:
dataSet.createComputedColumn('ComputedCol', new Function<SomeOtherClass> {
  SomeOtherClass apply(Long idx){
    new SomeOtherClass(col1.get(index) + col2.get(index).toString())
  }
}, isMaterialized) //isMaterialized flag enables storing calculated values for caching purposes

AFAIK, есть несколько полноценных решений BigData, таких как Apache Spark/Flink, которые поддерживают некоторые из перечисленных функций внутри или даже чистые механизмы хранения, такие как Apache ORC и Apache Parquet, но мне не удалось найти нужные API. Если какое-либо из этих решений отвечает нашим потребностям, дайте мне ссылку на соответствующий API или пример страницы.

0 ответов

Другие вопросы по тегам