Хранение и доступ к большому количеству относительно небольших файлов - PullRequest
0 голосов
/ 09 октября 2018

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

Итак, требования TL; DR:

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

Решения, которые я до сих пор пробовал:

  • сохранение их как отдельных файлов (один каталог на эксперимент, один двоичный файл на вычисления) - требует ручной обработки атомарности, а также большинство файловых систем поддерживают только имена файловдлиной до 255 символов (а имена вычислений могут быть длиннее), поэтому потребуется дополнительное отображение;также я не уверен, что ext4 (которая является файловой системой, которую я использую и не могу изменить) предназначена для обработки миллионов файлов
  • с использованием базы данных sqlite (только с одной таблицей и составным первичнымключ) - сначала это казалось идеальным, но когда мы получили сотни гигабайт данных (миллионы блобов ~ 100 КБ, и их число, и их размер увеличатся), это стало очень медленно, даже после применения найденных оптимизацийв интернете

Естественно, после сбоя sqlite первой идеей было просто перейти на «правильную» базу данных, такую ​​как postgres, но потом я понял, что, возможно, в этом случае реляционная база данных не совсемпуть (особенно потому, что скорость здесь критична, и мне не нужны большинство их функций) - и особенно postgres, вероятно, не тот путь, так как ближайший объект к BLOB-объекту - это bytea, который требует дополнительных преобразований (поэтомухит производительности гарантирован).Тем не менее, после небольшого исследования баз данных значения ключа (что, похоже, относится к моей проблеме), я обнаружил, что все проверенные базы данных не поддерживают составные ключи и часто имеют ограничения по длине для ключей (например, у couchbase есть только250 байт).Итак, я должен просто пойти с нормальной реляционной базой данных, попробовать одну из баз данных NoSQL, или, может быть, что-то совершенно другое, как HDF5?

1 Ответ

0 голосов
/ 15 марта 2019

Итак, я все равно использовал реляционную базу данных (поскольку только там я мог использовать составные ключи без каких-либо взломов).Я провел бенчмарк для сравнения sqlite с postgres и mysql - 500 000 вставок блобов ~ 60 КБ, а затем 50 000 выборок по всему ключу.Этого было недостаточно, чтобы замедлить sqlite до неприемлемых уровней, которые я испытывал, но установить точку отсчета (т. Е. Скорость, с которой sqlite работала с этими несколькими записями, была приемлемой для меня).Я предположил, что при добавлении большего количества записей с помощью mysql и postgres (поскольку они были разработаны для работы с гораздо большими объемами данных, чем sqlite), я не испытал бы значительного снижения производительности, а при использовании одного из них это оказалосьtrue.

Параметры (кроме значений по умолчанию) были следующие:

  • sqlite: режим журнала = wal (требуется для параллельного доступа), автокоммит уровня изоляции, значения как BLOB
  • postgres: автокоммит на уровне изоляции (не может отключить транзакции, и выполнение всего в одной огромной транзакции для меня не вариант), значения как BYTEA (что, к сожалению, включает двойное преобразование, о котором я писал)
  • mysql: engine = aria, транзакции отключены, значения как MEDIUMBLOB

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

                     sqlite     postgres        mysql
selects           90.816292   191.910514   106.363534
inserts         4367.483822  7227.473075  5081.281370

Mysql имел скорость, аналогичную sqlite, при этом postgres был значительно медленнее.

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