Обычно я бы просто использовал SQL / SQLite / Mongo для чего-нибудь, что связано с базами данных, но я подумал, что было бы интересно попробовать создать свою собственную структуру базы данных с плоскими файлами (это просто учебный проект). Само приложение представляет собой музыкальный стример с централизованной библиотекой на сервере.
База данных:
Мое приложение является клиент-серверным, поэтому любые изменения, сделанные сервером, синхронизируются со всеми клиентами. Серверы выполняют операции вставки, редактирования и удаления.
Клиенты могут изменять только логическое поле модификатора клиента в записи (значение которого зависит от этого клиента). Клиентам недоступны другие операции, поэтому НЕТ изменений для синхронизации.
Операции записи на сервере после первоначального построения базы данных выполняются редко, но все же происходят. Приоритетом здесь, безусловно, являются операции чтения для клиентов.
Должен быть масштабируемым до 500 тыс. Треков или размера файла базы данных 2 ГБ (2 ^ 31 байт) (в зависимости от того, что наступит раньше).
Что хранится:
- Несколько таблиц, с некоторыми отношениями. Это всего лишь макет, но вы поняли:
+--------+ +--------+ +-------------------+ | id* | | id* | | id* | | ARTIST | ------> | ARTIST | | track name | | | | ALBUM | ------> | ALBUM | | | | year | | length | | | | | | filename** | | | | | | {client modifier} | +--------+ +--------+ +-------------------+ * unique identifier ** not stored in client version of database {client modifier} is only on the client version of database
Одна проблема, которую необходимо решить, - это как работать с отношениями и поиском, чтобы минимизировать операции ввода-вывода.
- Все поля имеют переменную длину, кроме идентификатора, года и длины.
Обязательные функции:
- Сервер способен синхронизировать базу данных со всеми клиентами с минимальными операциями.
Один из способов приблизиться к этому - сохранить дату / время последнего изменения каждой записи и указать клиенту дату последней синхронизации. Когда клиент подключается к сети, все изменения, частично с этой датой, синхронизируются с клиентом. Другой способ сделать это - иметь отдельную таблицу на сервере, в которой перечислены все произошедшие операции и даты, когда они произошли; и выполните синхронизацию аналогичным образом.
- Операции быстрого чтения для клиентов
Из-за того, что таблицы меньше, клиент может хранить в памяти таблицы исполнителей и альбомов, но я предполагаю, что они этого не сделают.
я думал о том, чтобы создать отдельные файлы для каждой таблицы, и клиент всегда должен открывать каждый файл, чтобы они могли читать как можно быстрее ... это плохая идея?
Для каждой таблицы, с которой начинается каждая запись, необходимо будет сохранить какой-то индекс. Он может быть достаточно маленьким, чтобы загружаться в память, и может храниться в файлах отдельно от реальных таблиц, чтобы избежать проблем.
- Минимизируйте операции ввода-вывода
Сервер сохранит в памяти «индекс» базы данных треков с идентификатором и именем файла, поэтому операции чтения сведены к минимуму.
Сервер также будет буферизовать операции записи в базу данных, так что, если он обнаружит, что за короткий промежуток времени произойдет много операций записи, он подождет, а затем выполнит пакетную запись. Это возможно, потому что изменения в файловой системе по-прежнему останутся при сбое базы данных, поэтому можно просто перезагрузить все изменения при перезапуске.
- НЕ разреженный файл, чтобы уменьшить размер файла до минимума.
Я буду работать на уровне байтов, чтобы уменьшить размер файла. Основной проблемой будет фрагментация при удалении записи. Из-за полей переменной длины вы не можете просто добавить новую запись в это место.
Я мог бы де-фрагментировать файл, когда он достигнет определенного уровня фрагментации (отношения удаленных записей к записям), но я бы предпочел избежать этого, если смогу, поскольку это будет дорогостоящая операция для клиентов.
Я бы также не стал использовать поля фиксированной длины (например, имя файла может быть огромным), но они кажутся мне только параметрами?
Комментарии:
Итак, как мне добиться этого и максимизировать производительность?
Да, я пытаюсь изобретать велосипед, и да, я знаю, что, вероятно, я не смогу приблизиться к производительности других баз данных.
У кого-нибудь есть мысли / комментарии / идеи?
Спасибо за чтение.