Как хранить файлы в базе данных

Обновлено: 07.07.2024

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

Я тоже думал о возможности "ссылки" на эти файлы, но, возможно, это будет нести больше проблем, чем решений. Любой опыт в этом направлении будет приветствоваться :)

Примечание: база данных будет MySQL.

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

Итак, у вас будет столбец" местоположение "с частичным путем в нем, например " a/b/c / 1000", который вы затем сопоставляете к: "http://myserver/files/a/b/c/1000.mp3"

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

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

Я думаю, что хранение их в базе данных в порядке, если вы используете хорошую реализацию. Вы можете читать эту старую, но хорошую статью для идей о том, как сохранить большие объемы данных, влияющих на производительность.

У меня было буквально 100 концертов, загруженных в базы данных mysql без каких-либо проблем. Дизайн и реализация являются ключевыми, сделайте это неправильно, и вы будете страдать.

больше DB Преимущества (еще не упомянутые): - Работает лучше в среде с балансировкой нагрузки - Вы можете построить в более бэкэнд масштабируемости хранения

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

один совет, который у меня был бы об этом, заключается в том, чтобы хранить только "корневой относительный" путь к файлу в базе данных, а затем ваша программа или ваши запросы / хранимые процедуры/middle-ware используют конкретный корневой параметр установки для получения файл.

например, если вы храните XYZ.Wav in C:\MyProgram\Data\Sounds\X\ полный путь будет

но вы бы сохранить путь и имя файла в базе данных, как:

в другом месте, в базе данных или в файлах конфигурации вашей программы, сохраните корневой путь, такой как SoundFilePath, равный

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

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

преимущества использования базы данных:

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

недостатки использования базы данных:

  • раздувание базы данных
  • базы данных могут быть дороже, чем файловые системы

вы можете хранить их как BLOBs (или LONGBLOBs), а затем извлекать данные, когда вы хотите получить доступ к медиа-файлам.

вы можете просто хранить медиафайлы на диске и хранить метаданные в БД.

Я склоняюсь к последнему методу. Я не знаю, как это делается в целом в мире, но я подозреваю, что многие другие делали то же самое.

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

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

вот как я это делаю. Уверен, у других тоже будут идеи.

некоторые преимущества использования blobs для хранения файлов

  • более низкие накладные расходы на управление-используйте один инструмент для резервного копирования / восстановления и т. д.
  • нет возможности для базы данных и файловой системы для синхронизации
  • транзакционная возможность (при необходимости)
  • взрывает ОЗУ ваших серверов баз данных с бесполезным мусором, который он может использовать для хранения строк, индексов и т. д.
  • делает ваши резервные копии БД очень большой, следовательно, менее управляемый
  • не так удобно, как файловая система для обслуживания клиентов (например, веб-сервер)

Что насчет производительности? Ваш пробег может отличаться. Файловые системы чрезвычайно разнообразны, как и базы данных в их производительности. В некоторых случаях файловая система выиграет (возможно, с меньшим количеством больших файлов). В некоторых случаях БД может быть лучше (возможно, с очень большим количеством небольших файлов).

в любом случае, не волнуйтесь, делайте то, что кажется лучший в то время.

некоторые базы данных предлагают встроенный веб-сервер для обслуживания blobs. На момент написания статьи MySQL этого не делает.

храните их как внешние файлы. Затем сохраните путь в поле varchar. Помещение больших двоичных двоичных объектов в реляционную базу данных обычно очень неэффективно - они используют только пространство и замедляют работу по мере заполнения кэшей. И ничего не добьешься - сами капли не могут быть найдены. Однако вы можете сохранить метаданные мультимедиа в базе данных.

простым решением было бы просто сохранить относительные местоположения файлов в виде строк и позволить файловой системе обрабатывать их. Я пробовал это в проекте (мы хранили вложения файлов office в опрос), и он работал нормально.

Современные базы данных могут хранить самые различные виды информации. В том числе, целые файлы.

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

Современные системы управления, базами данных, включая Microsoft SQL Server (MS SQL), и средства программирования прекрасно справляются с данной задачей.

Существуют два способа хранения файлов в базах данных MS SQL.

  • Хранение файла в поле с двоичными данными (тип данных VARBINARY(MAX));
  • Использование файловых таблиц.

Второй способ стал доступен вместе с появлением файловых таблиц в MS SQL 2012 и в более ранних версиях его использование не возможно. Первый способ поддерживают все без исключения версии MS SQL (включая 2014) и он является, по сути, универсальным. Именно он и будет рассмотрен в данной статье.

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

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

Вот примерный вариант такой таблицы:

  • id – уникальный идентификатор. Первичный ключ;
  • fileName – строковое поле (например, nvarchar(255)) с именем файла;
  • binaryData – поле с двоичными данными (VARBINARY(MAX)) в котором собственно и хранится файл.

Рассматриваются и сравниваются параметры, доступные для хранения файлов и документов в SQL Server.

Хранение файлов в базе данных — преимущества и ожидания

Большая часть корпоративных данных является по своей природе неструктурированной и обычно хранится в виде файлов и документов в файловой системе. Большая часть этих данных производится, управляется и используется приложениями, осуществляющими доступ к файлам через API-интерфейсы Windows. Обычно компании хранят эти данные в файловой системе, а метаданные для них — в реляционной базе данных.

Интеграция неструктурированных данных в реляционную базу данных дает следующие преимущества:

  • Возможности интегрированного хранения и управления данными, например резервное копирование.
  • Интегрированные службы, такие как полнотекстовый поиск и семантический поиск в данных и метаданных.
  • Простота администрирования и управления политиками для неструктурированных данных.

Однако, как правило, хранить неструктурированные данные в реляционных базах данных было неудобно. Переписывать работающие приложения (Microsoft Word, Adobe Reader и т. д.) для обеспечения взаимодействия через API-интерфейсы реляционной базы данных было непрактично. Этим приложениям нужно, чтобы данные были доступны через API-интерфейсы Windows. Приложения предъявляют указанные ниже требования.

  • Приложения Windows не поддерживают транзакции в базах данных и не требуют их.
  • Приложения Windows требуют совместимости с API-интерфейсами файловой системы для данных из файлов и каталогов.

В прошлом в SQL Server не были предусмотрены способы хранения неструктурированных данных в реляционных базах данных. Однако в настоящее время такие способы предлагаются.

FILESTREAM

В SQL Server уже имеется функция FILESTREAM. Она обеспечивает эффективное хранение и потоковую передачу неструктурированных данных, хранящихся в виде файлов в файловой системе, а также управление ими. Тем не менее для решения FILESTREAM требуется дополнительное программирование, оно не удовлетворяет требованиям полной совместимости с приложениями Windows, описанным выше.

Таблицы FileTable

Функция FileTable построена на основе существующих возможностей технологии FILESTREAM. Она позволяет корпоративным клиентам хранить неструктурированные файловые данные и иерархии папок в базе данных SQL Server. Эта функция обеспечивает доступ к данным без транзакций и совместимость приложений Windows с данными, хранящимися в файлах.

Сравнение FILESTREAM и таблиц FileTable

Компонент Файловый сервер и решение для базы данных Решение FILESTREAM Решение FileTable
Одно решение для задач управления нет Да Да
Один набор служб: поиск, отчеты, запросы и т. д. нет Да Да
Интегрированная модель безопасности нет Да Да
Обновление на месте для данных FILESTREAM Да Нет Да
Иерархия каталогов и файлов сохраняется в базе данных нет Нет Да
Совместимость с приложениями Windows Да Нет Да
Реляционный доступ к атрибутам файлов нет Нет Да

Сравнение FILESTREAM и удаленного хранилища больших двоичных объектов (RBS)

Еще один вариант хранения неструктурированных данных — Удаленное хранилище больших двоичных объектов (RBS). Дополнительные сведения см. в статье Удаленное хранилище больших двоичных объектов (SQL Server).

Узнайте, как хранить файлы в базе данных в виде больших объектов или как использовать базу данных в качестве индекса файловой системы.

1. Обзор

Когда мы создаем какое-то решение для управления контентом, нам нужно решить две проблемы. Нам нужно место для хранения самих файлов, и нам нужна какая-то база данных для их индексации.

Можно хранить содержимое файлов в самой базе данных, или мы можем хранить содержимое в другом месте и индексировать его вместе с базой данных.

В этой статье мы проиллюстрируем оба этих метода с помощью базового приложения для архивирования изображений. Мы также реализуем API-интерфейсы REST для загрузки и загрузки.

2. Пример использования

Наше приложение для архивирования изображений позволит нам загружать и скачивать изображения в формате JPEG .

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

Мы будем использовать реляционную базу данных с Spring Data JPA и Hibernate .

3. Хранение Базы данных

Давайте начнем с нашей базы данных.

3.1. Сущность изображения

Во-первых, давайте создадим наш Образ объект:

Поле id аннотируется символом @GeneratedValue . Это означает, что база данных создаст уникальный идентификатор для каждой добавляемой нами записи. Индексируя изображения с этими значениями, нам не нужно беспокоиться о том, что несколько загрузок одного и того же изображения будут конфликтовать друг с другом.

Во-вторых, у нас есть аннотация Hibernate @Lob|/. Это то, как мы сообщаем JPA о нашем намерении хранить потенциально большой двоичный файл .

3.2. Хранилище изображений

Далее нам нужен репозиторий для подключения к базе данных .

Мы будем использовать spring JpaRepository:

Теперь мы готовы сохранить наши изображения. Нам просто нужен способ загрузить их в наше приложение.

4. Контроллер ОТДЫХА

Мы будем использовать MultipartFile для загрузки наших изображений. Загрузка вернет идентификатор изображения , который мы можем использовать для загрузки изображения позже.

4.1. Загрузка изображений

Давайте начнем с создания нашего Контроллера изображений для поддержки загрузки:

Объект MultipartFile содержит содержимое и исходное имя файла. Мы используем это для построения нашего объекта Image для хранения в базе данных.

Этот контроллер возвращает сгенерированный идентификатор в качестве тела своего ответа.

4.2. Загрузка изображений

Теперь давайте добавим маршрут загрузки :

5. Тест Архива изображений базы данных

Теперь мы готовы протестировать наш архив изображений.

Во-первых, давайте создадим наше приложение:

Во-вторых, давайте запустим его:

5.1. Тест загрузки изображений

После запуска нашего приложения мы используем инструмент командной строки curl для загрузки нашего изображения :

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

5.2. Тест загрузки изображений

Затем мы можем загрузить наше изображение:

-o image.jpg опция создаст файл с именем image.jpg и хранить в нем содержимое ответа:

6. Раздельное содержание и расположение

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

Еще одним хорошим вариантом является загрузка содержимого файла в другое место. Затем мы сохраняем только его файловую систему местоположение в БД .

Для этого нам нужно будет добавить новое поле в нашу сущность Image :

Это будет содержать логический путь к файлу в некотором внешнем хранилище. В нашем случае это будет путь к файловой системе нашего сервера.

Однако мы можем в равной степени применить эту идею к разным магазинам. Например, мы могли бы использовать облачное хранилище – Google Cloud Storage или |/Amazon S3 . В этом расположении также может использоваться формат URI, например s3://некоторый ведро/путь/к/файлу .

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

7. Хранилище файловой системы

Давайте добавим в наше решение возможность хранить изображения в файловой системе .

7.1. Сохранение в файловой системе

Во-первых, нам нужно сохранить ваши изображения в файловой системе:

Одно важное замечание – мы должны убедиться, что каждое из наших изображений имеет уникальное местоположение определенное на стороне сервера во время загрузки . В противном случае наши загрузки могут перезаписать друг друга.

То же правило будет применяться к любому облачному хранилищу, где мы должны создавать уникальные ключи. В этом примере мы добавим текущую дату в формате миллисекунд к имени изображения:

7.2. Извлечение Из Файловой системы

Теперь давайте реализуем код для извлечения нашего изображения из файловой системы:

Здесь мы ищем изображение, используя его местоположение . Затем мы возвращаем FileSystemResource .

7.3. Потоковая передача данных и ресурс Spring

Наш метод find In FileSystem возвращает FileSystemResource , реализацию интерфейса ресурса//Spring.

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

Этот подход является хорошим общим решением для потоковой передачи файлов клиенту. Если мы используем облачное хранилище вместо файловой системы, мы можем заменить FileSystemResource для реализации другого ресурса, например InputStreamResource или ByteArrayResource .

8. Подключение содержимого и местоположения файла

Теперь, когда у нас есть репозиторий Файловой системы, нам нужно связать его с нашим репозиторием Image Db.

8.1. Сохранение в базе данных и Файловой системе

Давайте создадим Службу определения местоположения файлов , начиная с нашего потока сохранения:

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

8.2. Извлечение из Базы данных и Файловой системы

Теперь давайте создадим метод, чтобы найти наше изображение, используя его id :

Во-первых, мы ищем наше изображение в базе данных . Затем мы получаем его местоположение и извлекаем его из файловой системы .

9. Загрузка и загрузка файловой системы

Наконец, давайте создадим контроллер образа файловой системы :

Затем мы создали маршрут загрузки , аналогичный тому, что был в нашем контроллере Image , но без объекта db Image .

10. Тест архива изображений Файловой системы

А потом мы скачиваем:

11. Заключение

В этой статье мы узнали, как сохранить информацию о файле в базе данных с содержимым файла либо в той же строке, либо во внешнем расположении.

Мы также построили и протестировали REST API с использованием многоступенчатой загрузки, и мы предоставили функцию загрузки с использованием Resource , чтобы разрешить потоковую передачу файла вызывающему абоненту.

Читайте также: