Структура данных / алгоритм хранения и поиска записей переменной длины на диске с поиском только по первичным ключам - PullRequest
5 голосов
/ 17 мая 2009

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

Кажется, что B-дерево является часто цитируемой структурой, но в основном для записей фиксированной длины. Я также ожидаю значительно большего количества загрузок и обновлений, чем вставляю и удаляю. Можно ли избавиться от поиска O (log m) B-дерева?

Я очень рад, что это комбинированная система, например, ISAM объединяет B-дерево и линейное хранилище файлов, которое выглядит так, будто его можно использовать для работы с записями переменной длины в качестве подхода. Есть ли что-то лучше?

Некоторые дополнительные ограничения:

1) Идентификаторы потенциально разрежены, но их можно создать в виде блоков линейных чисел, но в большом диапазоне (64 бита)

2) Я не хочу использовать СУБД, производительность для моей конкретной проблемы не очень хорошая. Мне не нужны никакие операции, которые использует полная СУБД, мне не нужен поиск. Мне нужно что-то, что я могу легко настроить и оптимизировать. Назовите это академическим любопытством, если MySQL его не использует, тогда я воспользуюсь им, но мне нужно постараться быстрее.

3) Набор данных больше, чем может поместиться в памяти, однако индекс может вполне уместиться в памяти, если его просто сместить как ключ. Я, конечно, смотрю что-то вроде 1 миллиарда или более объектов в хранилище.

4) В идеале пространство должно быть восстановлено при удалении записи. Это может быть с помощью сжатия, но мне интересно посмотреть, есть ли лучший способ (например, B-дерево легко восстанавливает пространство).

Ответы [ 4 ]

10 голосов
/ 18 мая 2009

Простой способ: использовать что-то вроде Berkeley DB. Он предоставляет хранилище значений ключей для произвольных байтовых строк и выполняет всю тяжелую работу за вас. Он даже предоставляет «вторичные базы данных» для индексации, если вы этого хотите.

Способ "сделай сам": используйте буферы протокола (или двоичный формат по вашему выбору), чтобы определить узел B-Tree и структуры элементов данных. Используйте файл только для добавления для вашей базы данных. Чтобы записать новую запись или изменить существующую запись, вы просто записываете саму запись в конец файла, а затем записываете любые измененные узлы B-Tree (например, родительский узел записи, ее родительский узел, и так далее до корня). Затем запишите местоположение нового корня дерева в блоке заголовка в начале файла. Чтобы прочитать файл, просто найдите самый последний корневой узел и прочитайте B-дерево, как в любом другом файле. Этот подход имеет несколько преимуществ:

  • Поскольку записанные данные никогда не изменяются, читателям не нужно брать блокировки и получать представление «моментального снимка» БД на основе корневого узла в момент начала чтения.
  • Добавляя поля «предыдущая версия» к своим узлам и записям, вы получаете возможность доступа к предыдущим версиям БД практически бесплатно.
  • Это действительно легко реализовать и отладить по сравнению с большинством форматов файлов на диске, которые поддерживают модификацию.
  • Сжатие базы данных состоит из простого считывания последней версии данных и B-Tree и записи их в новый файл.
0 голосов
/ 18 мая 2009

Лучше всего использовать коммерческое ядро ​​базы данных.

Вы можете избавиться от любого поиска O (log m) B-дерева, сохранив индекс, т.е. {"логический идентификатор" сопоставляется с парами значений "физическое местоположение"} в хэш-карте (хеширование на логический идентификатор) ... или, даже, сохранение индекса в непрерывном векторе (с использованием логического идентификатора в качестве индекса для вектора значений смещения), как предположил bdonlan, если значения идентификатора не редки.

Важная деталь реализации может заключаться в том, какой API вы используете для доступа к индексу: сохраняете ли вы его в ОЗУ (которое O / S поддерживает с файлом системной страницы) и обращаетесь к нему в процессе работы, используя указатели, и / или сохраните его на диске (который O / S кэширует в кеше файловой системы) и получите к нему доступ через API файлового ввода / вывода.

0 голосов
/ 18 мая 2009

Если база данных слишком тяжелая для вас, рассмотрите хранилище значений ключей.

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

0 голосов
/ 17 мая 2009

Если ваши идентификаторы являются числами и не очень разреженными, одним из вариантов будет использование простой таблицы (смещение, длина) в одном файле со ссылкой на данные в другом файле. Это даст вам O (1) поиск и обновит / вставит / удалит привязку только вашим механизмом отслеживания свободного пространства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...