LINUX.ORG.RU

Хранилище или СУБД для множества blob данных

 , , ,


0

1

Просьба посоветовать, что посмотреть из дисковых хранилищ/key-value СУБД со следующими требованиями:

  • Хранение blob значений по ключам или путям (число или строка, не важно).
  • Сущностей для хранения много (порядка 10 млн), все они - бинарные блобы разных размеров - от 100Кб до 1Гб.
  • Нужен быстрый random-access на чтение/запись. Намного быстрее, чем хранить каждую из сущностей в виде отдельного файла в фс (это проверено, очень медленно при росте числа файлов).
  • Все хранится на одной машине, не распределенно
  • Не слишком большой оверхед по занимаемому месту на диске
  • С или C++ API

Копалось в сторону штук типа leveldb, проприетарных хранилищ и собственного велосипеда, все показывает сильное падение скорости доступа при росте числа значений или просто константно-низкую скорость (порядка 0.1 от скорости диска)

это проверено, очень медленно при росте числа файлов

Проверено на чём? Вряд ли можно придумать для решения что-то быстрее, чем ФС на базе b-tree.

no-such-file ★★★★★ ()
Ответ на: комментарий от no-such-file

Можно конечно. ФС очень общий механизм. BTree не самая быстрая штука, и призвана уменьшить число дискового I/O при lookup по файловой таблице. В моей же задаче можно просто всю таблицу ключ->смещение в хранилище держать в памяти все время работы, чего себе не может позволить ФС. ФС решает задачу минимального расхода дискового пространства, в том числе фрагментируя файлы. В моей задаче перерасход в разумных пределах допустим, фрагментация не нужна и ее быть не должно. Ну и тд.

CatsCantFly ()
Последнее исправление: CatsCantFly (всего исправлений: 1)

Бинарный блоб это сильно конечно.

Нужен быстрый random-access на чтение/запись.

Это не описание задачи. Запись разная бывает. Она может менять структуру, а может не менять. В контексте плоских данных - их длину.

Если меняет - в общем случае это невозможно. Если меняет как-то особенно - уже можно думать.

В любом случае от фрагментации ничего не спасёт.

собственного велосипеда, все показывает сильное падение скорости доступа при росте числа значений или просто константно-низкую скорость (порядка 0.1 от скорости диска)

По какому принципу работал твой велосипед? Даже самый наивный велосипед не может работать настолько хреново.

anonymous ()
Ответ на: комментарий от anonymous

ssd быстрый за счёт высокого уровня параллелизма. Сам по себе ssd не особо быстрее харда. Очевидно, что то там явно какое-то размазанное говно кое как слепленное на блокирующих ридах/врайтах в лучшем случае.

По этой причине либо ты пишешь +/- последовательно, что-бы ОС/железяка сделали всё сами. Либо каким-то образом организуешь конкурентный доступ, что-бы ОС/железо опять сделали всё сами. Ни здесь никакого быстро у тебя не будет. Будет лишь быстрее харда.

anonymous ()
Ответ на: комментарий от CatsCantFly

В моей же задаче можно просто всю таблицу ключ->смещение в хранилище держать в памяти все время работы

фрагментация не нужна и ее быть не должно

Тогда не понятно, в чём вопрос? Работай с диском также как с оперативной памятью и всё.

no-such-file ★★★★★ ()
Последнее исправление: no-such-file (всего исправлений: 1)
  1. Самым простым решением будет использование файловой системы. Определенная сложность в разработке отображения значения ключа в иерархический путь в хранилище. Также важно выбрать подходящий размер блока. Как вариант можно именовать и раскладывать файлы по sequence, а соответствие ключа и номера хранить в libmdbx (если нужно быстро), либо в sqlite (если нужен sql). Также стоит посмотреть на git large file storage.

  2. Для 64-битной платформы подойдет libmdbx. Особенно в режиме MDBX_WRITEMAP с размером страницы в 64К и опцией MDBX_RESERVE при заливке гигабайтных записей. Это вариант наверное самый быстрый, т.е. с минимальными накладным расходами (поиск в разы быстрее чем в fs или sqlite) и линейным чтением с диска больших записей. Обещано что скоро у либы будет интерфейс C++.

  3. Упомянутый Rados может быть вариантом, однако есть «но»: пропорция «один конь : один рябчик» с вашим кодом, затраты на поддержку инфраструктуры, (скорее всего) СУБД для трансляции ваших ключей в objectid, накладные расходы. Тем не менее, для записей размером в мегабайты и более, это может быть адекватным решением.

anonymous ()

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

Случайно не все файлы в паре-тройке каталогов? Возможно ещё проверка прав доступа подтормаживает

DllMain ()

Сектанты-эникеи прибежали тереть. В общем мне насрать на эту помойку. Но раз ответ написал запощу. А то судя по рассуждениям автора он не реализовал даже минимально-адекватной схемы. Она описана ниже.

Я даже тебе помогу, авось тебе непонятно. Автор говорит про файлы от 100к. Хорошо.

Минимальный размер блока - 100к. Прикручиваем к этому блоку заголовок. Заголовок должен содержать 1) id хранимой сущности, 2) позицию в рамках этой сущности. 3) размер данных в рамках блока.

Всё, далее поверх этого создаёшь в памяти индекс. id -> список блоков. Всё это можно ммапить на одно адресное пространство.

Для оптимизации индекса можно ввести «над-блоки». Т.е. к блоку можно прицепить ещё сколько угодно блоков подряд.

В рамках это организации без проблем обеспечивается дополнительное пространство для роста сущностей.

Судя по словам автора фрагментации у него нет, а даже если есть - это не проблема заребилдить. Подобная схема не имеет прямой адресации и в любой момент любые данные могут быть перенесены. Прозрачная и почти бесплатная онлайн-дефрагментация.

К этому нежно добавить пердолинг, если необходимо какое-либо надёжное хранение. Без проблем прикручивается cow, чексуммы и прочее.

Самая простая схема, почти идеально быстрая и реализуемая за вечер-два. Ты больше убьёшь времени на предолинг со всяким говном птушным.

anonymous ()

чепуха какая-то. Возмите обычную иерархию директорий /path/to/fi/l/e на объемах в единицы терабайт и неск миллионов файлов пропускная способность sas-дисков(hdd) полностью утилизируется

anonymous ()