Замена огромного файла дампа эффективным текстовым хранилищем Java с поиском по ключу и значению

У меня есть огромный файл дампа — 12 ГБ текста, содержащего миллионы записей. Каждая запись имеет числовой идентификатор, некоторый текст и другие не относящиеся к делу свойства. Я хочу преобразовать этот файл во что-то, что обеспечит эффективный поиск. То есть, учитывая идентификатор, он быстро вернет текст. Ограничения:

  1. Встроен в Java, желательно без внешнего сервера или зависимостей от иностранного языка.
  2. Читает и пишет на диск, а не в память - у меня нет 12гб ОЗУ.
  3. Не сильно раздувает - не хочу превращать файл 12гб в индекс 200гб. Мне не нужен полнотекстовый поиск, сортировка или что-то необычное — просто поиск по ключу-значению.
  4. Эффективность — данных много, а у меня всего одна машина, поэтому проблема со скоростью. Предпочтение отдается инструментам, которые могут хранить большие пакеты и/или хорошо работать с несколькими потоками.
  5. Хранение более одного поля — это хорошо, но не обязательно. Основная проблема — текст.

Ваши рекомендации приветствуются!


person Little Bobby Tables    schedule 06.12.2012    source источник
comment
Вы должны указать формат вашего дампа.   -  person    schedule 06.12.2012
comment
Имеет ли значение формат? Похоже, его нужно загрузить в какое-то хранилище, и, следовательно, исходный формат не имеет отношения к этому вопросу.   -  person Brian Agnew    schedule 06.12.2012
comment
@BrianAgnew Я думал, что если по одной строке на запись, он мог бы создать индекс вручную id=>lineNumber   -  person    schedule 06.12.2012
comment
@RC Какой-то тривиальный XML, где каждая запись представляет собой отдельный тег. Однако полнофункциональная база данных XML была бы излишеством, поскольку она не имеет иерархической структуры. Возможно, это был CSV, и проблема осталась бы прежней.   -  person Little Bobby Tables    schedule 06.12.2012
comment
@RC, использующий номер строки вместо заданного идентификатора, является интересной идеей: насколько быстро Java извлекает одну строку из файла размером 12 ГБ? Я не уверен, что смогу использовать этот трюк в одиночку, потому что есть несколько перекрестных ссылок.   -  person Little Bobby Tables    schedule 06.12.2012
comment
@LittleBobbyTables не знает, это была просто сумасшедшая идея   -  person    schedule 06.12.2012


Ответы (2)


Я бы использовал Java Chronicle или что-то подобное (частично потому, что я написал это), потому что это предназначен для случайного доступа к большим объемам данных (больше, чем ваша машина).

Он может хранить любое количество полей в текстовом или двоичном формате (или в комбинации, если хотите). Он добавляет 8 байтов на запись, к которой вы хотите иметь произвольный доступ. Он не поддерживает удаление записей (вы можете пометить их для повторного использования), но вы можете обновлять и добавлять новые записи.

У него может быть только один поток записи, но он может быть прочитан несколькими потоками на одной машине (даже разными процессами).

Он не поддерживает пакетную обработку, но может читать/записывать миллионы записей в секунду с типичной задержкой менее микросекунды (за исключением случайных операций чтения/записи, которые не находятся в памяти).

Он почти не использует кучу (‹1 МБ для ТБ данных)

Он использует последовательный идентификатор, но вы можете создать таблицу для выполнения именно этого перевода.

Кстати: вы можете купить 32 ГБ менее чем за 200 долларов. Возможно, пришло время получить больше памяти;)

person Peter Lawrey    schedule 06.12.2012
comment
Работает ли Chronicle в памяти или кеширует на диск? - person Little Bobby Tables; 06.12.2012
comment
Он использует файлы с отображением памяти, поэтому дисковый кеш ОС доступен непосредственно в Java. Это означает, что чтение и запись на диск выполняются операционной системой прозрачно. то есть, сколько в памяти и как на диске имеет большое значение (на самом деле это невозможно сказать из Java) и зависит от того, сколько у вас свободных ресурсов. Кстати, для работы требуется 64-битная JVM, поскольку она использует виртуальную память. - person Peter Lawrey; 06.12.2012

Почему бы не использовать JavaDb — базу данных, поставляемую с Java?

Он будет хранить информацию на диске и будет эффективен с точки зрения поиска, если вы правильно проиндексируете. Он будет работать в JVM, поэтому вам не нужен отдельный сервер/служба. Вы говорите с ним, используя стандартный JDBC.

Я подозреваю, что это будет довольно эффективно. Эта база данных имеет долгую историю (раньше это была Derby от IBM), и на нее было затрачено много усилий с точки зрения надежности и эффективности.

Вам, очевидно, потребуется выполнить первоначальную адаптацию данных для создания базы данных, но это разовая задача.

person Brian Agnew    schedule 06.12.2012