Почему не стоит хранить файлы в бд

Обновлено: 07.07.2024

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

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

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

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

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

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

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

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

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

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

Хотелось бы увидеть + и - различных видов хранения, и когда какой лучше использовать.

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

UPD: Enttity Framework дружит с файловыми таблицами?


24.1k 8 8 золотых знаков 48 48 серебряных знаков 135 135 бронзовых знаков А вы тут на SO в поиске не вводили "файлы в базе", подобные вопросы примерно раз в месяц проходят . И собственно что такое "файловая таблица" ? А большинство написанных вами предположений неверно. 1. Процесс может блокировать файл. 2. нет транзакций. 3. как писать файл и игнорировать при этом отваливание клиента или нет решать вам. Если машина неожиданно перезагрузится или произойдет другой сбой недописанный файл может остаться на диске

В SqlServer вы можете использовать следующие варианты (некоторые из них применимы и к другим СУБД).

Вариант 1

В БД хранится "заголовок" файла (например, путь к файлу плюс, возможно, какой-то набор атрибутов):

а данные хранятся отдельно в файловой системе. Размер БД меньше, чем если хранить в БД также и данные. Но нужно следить за ситуациями "файл есть, заголовка нет" или "заголовок есть, файла нет". На мой взгляд, если файлы являются логически важной частью данных БД (не кэш, не какие-то временные данные), то лучше посмотреть на другие варианты.

Вариант 2

В БД хранится также и содержимое файла (в столбце типа varbinary(max) ).

Здесь две опции - с FILESTREAM и без.

  • данные хранятся в БД (в т.н. LOB pages)
  • размер данных одного элемента ограничен 2Gb
  • данные хранятся в файловой системе (именно как файлы)
  • нет ограничения в 2Gb на элемент
  • данные FILESTREAM не участвуют при подсчёте лимита на макс. размер БД (к чему чувствительны Express Edition)
  • к данным можно получить доступ через соотв. API со стороны файловой системы
  • (SqlServer 2014 и далее) запрашиваемые данные не отъедают из buffer pool, оставляя больше памяти для обработки запросов

И с FILESTREAM и без поддерживаются транзакции. С FILESTREAM при доступе через Transact-SQL поддержка полная, при доступе через файловую систему есть ограничения (смотреть здесь).

Вариант 3

Использование таблиц специального типа FileTable.

Их функционал основан на использовании FILESTREAM . Таблица представляет иерархию хранящихся файлов/директорий, их данные и атрибуты. В варианте 2, чтобы создать/удалить файл, нужно создать/удалить соотв. запись в таблице. В данном варианте это можно делать напрямую через файловую систему. Например зайти в соответствующую директорию (SqlServer создаёт для этого соответствующую UNC share), создать какой-то файл/директорию, удалить/изменить, потом сделать запрос select * from FileTableName и увидеть соответствующие изменения. И наоборот - при вставке записи в таблицу через SQL в директории появится соответствующий файл или директория.

Какой вариант когда лучше использовать - думаю, зависит от конкретной задачи. В документации более детальное описание и сравнение вариантов 2 и 3.

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

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

Базы данных тоже в файлах хранятся. Накой чёрт нужна эта прослойка.

ясно, что не в астрале, чтобы избежать вот этого:

необходимости городить систему каталогов в файловой системе и от необходимости следить за синхронностью между файловым хранилищем и базой данных?

это ложится на плечи бд

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


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

Если какую нибудь специализированную субд не использовать, то доступ к данным будет медленнее.

p.s. Если будешь делать так - то 2 таблицы: с собственно файлами и вторая с названиями файлов (ну и другими полями по которым нужна сортировка).

pi11 ★★★★★ ( 16.06.13 22:25:16 )
Последнее исправление: pi11 16.06.13 22:25:46 (всего исправлений: 1)


З.Ы. Заметь, что плодить набор директорий на современных ОС уже давно бессмысленно.

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

Мха ха ) . Неговори.

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

да я в предыдущем своем вопросе все примерно описал, фотографии, видео, аудио и наверно документы, просто меня напрягает возможная ситуация, когда запись в бд есть, а файла по каким-то причинам не оказалось или наоборот файл лежит в файловой системе, а записи нет, пользователи, весьма вероятно, будут активно скачивать и аплолдить файлы, однако пользователей не много, 10 - 15 человек. Файлов 1 - 2 терабайт, количество не известно, но можно приблизительно посчитать.


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

В какой базе данных? _Разные_ СУБДы много лет задачивались под _разные_ задачи. Вероятно, среди них не удастся найти ни одной, заточенной под обработку блобов лучше, чем адекватная файловая система. Так зачем баян?

необходимости следить за синхронностью между файловым хранилищем и базой данных

просто я перфикционист и мне будет не приятно об этом узнать

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

ясно, работать буду по феншую

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

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


у тебя клиент напрямую с базой работает или есть промежуточный сервер?


Есть вполне успешные проекты, которые хранят терабайты котиков в gridfs на монге.

Тут все очень сильно зависит от задач. У себя вот как раз планирую gridfs использовать. Потому что небольшое потенциальное замедление не критично, а профит от простоты управления - весьма заметный.


GridFS в монге якобы заточили. Мопед не мой. Но с рулевым одной из команд, которая подобное использует, пообщаться довелось.

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

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

всем спасибо за ответы

Да! Так действительно легче когда их мало и разновидностей их тоже мало (ну или очень много уникальных) . Зачем использовать БД для хранения, к примеру, файла записей с двумя полями, кол-во которых не больше десятка или двух десятков уникальных записей.
Но, в большинстве случаев, приходится работать с огромной кучей однотипных данных. Например: сведения о заказчиках, тел. справочник, прайс-листы и т. д. Количество единиц этих данных, обычно, бывает очень большое (телефонный справочник города Москвы).. .
Любой хороший программист в состоянии реализовать небольшую БД для собственных нужд (затратив на её разработку больше времени чем на весь проект).. . Но зачем? Когда это может сделать группа профессионалов и намного лучше. Программисту останется только научиться работать с функциями. Конечно есть накладные расходы. Но они компенсируются приростом производительности.
И еще важный момент. Абстракция. Базы данных дают возможность организовать правильное хранение данных.

Базы данных, обычно, как раз и хранят данные в файл (е) ах.. .
Ну и вообще баз данных немало видов придумано было.. .
P.S. Википедия: "По принципу иерархической БД построены иерархические файловые системы и Реестр Windows."

Базы данных-это особые таблицы, способные взаимодействовать со скриптами на сайте, которые в Word-e сделать невозможно. а если я сайт не делаю, то лучше в файле хранить данные? Sкушаlкег G-Style Гуру (3834) Смотря по обьему. Ведь 1С Предприятие-тоже база данных. данные в файле и хранятся, а вот его структурный вопрос - это уже другое файл - это просто текст. а базы данных - это структура в виде таблицы. Чудо Искусственный Интеллект (152096) текст исходного кода, :) Чудо Искусственный Интеллект (152096) речь идет о данных, а не о кино. а я храню в файле и все работает! Получается что реально. ну как обоснуй, Санек. Linux, например построен на взаимодейсвии файлов, даже устройства как файлы определятся(ну это так к слову) Понял, хоть что ляпнул? База данных это и есть файловые данные. Просто для удобства существуют механизмы отбора, что-бы из миллиардов записей найти ту, что тебе нужна, а не перерывать все миллионы. Чтобы облегчить поиск данных. И работать только с необходимыми. Личный Кабинет Удалён Мыслитель (9996) Но не все они могут понадобиться в данный момент времени. да и сам файл. элемент базы данных :-) хранить легче, искать нужную информацию-легче повеситца!

Базы данных обеспечивают более быстрый (ОЧЕНЬ БЫСТРЫЙ) доступ к информации за счет специальной структуры хранения данных. Кроме того в базах данных имеется удобный язык запросов SQL, помощью которого можно делать сложные запросы данных. А еще базы данных ориентированы на то, чтобы данные запрашивали сразу несколько субъектов.

Например, числовые таблицы вы можете хранить в обычном текстовом файле *.txt и использовать Блокнот для их просмотра и редактирования. А можете воспользоваться Excel, который предоставляет вам более мощные и удобные средства для работы с таблицами. Также и СУБД MySQL, Oracle, MSSQL и т. д. предоставляют вам более мощные и удобные инструменты для хранения информации.

Ты никогда не пробовал хранить все свои документы в одной коробке? чтобы оперировать с данными в файле - тебе придется писать свой движок для выполнения запросов. а субд - это и есть тот самый движок. так что зачем изоретать велосипед? тем более текстовыми файлами для хранения данных пользуются только быдлокодеры. нормальный программисты работат с бд. имхо - лучше использовать sqlite - Он не требует регистрации в системе, достаточно кинуть дллку в папку с программой а почему текстовыми файлами для хранения данных пользуются только быдлокодеры? CODEMASTER Мастер (1402) re>>а почему текстовыми файлами для хранения данных пользуются только быдлокодеры? потому что не факт, что файл будет правильного формата(мало ли - вдруг юзер сам полез паравить файл, или кодер допустил ошибку в алгоритме записи в файл) - могут быть практически любые ошибки - от простого исключения(raised exception) До переполнения буфера и порчи данных, что не есть гуд когда ты пишишь приложение для серьезного предприятия, потря данных для которого моджет приченить серьезный ущерб. так что пользуйся базами данных и все будет ок.

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

СУБД ведет работу не с чем-то там, а именно с теми самыми "данными в файле", так как файлы БД они хранятся в виде физических файлов на жестком диске, только в отличии от обычного тупого считывания там применяются специальные алгоритмы (файловые индексы) итп, что гарантирует более быстрое получение результата. Говорить, что хранить данные просто в файле удобнее - это не совсем верно, так как в обычном программировании считывание файла довольно ограничено рамками времени выполнения программы, что не позволяет в полной мере использовать возможности кеш. Более того постоянное обращение непосредственно к жесткому диску для скачивания файла сегодня считается как долгим так и ирроциональным процессом :) Потому и понадобился отдельный, постоянно висящий на некотором порту, сервер БД; наличие такой отдельной программы СУБД, которая не зависит от клиентского приложения и его времени выполнения, как раз и позволяет в полной мере использовать кеш (те же индексы) , чтобы доступ к данным с помощью считывания файла был сведем к самому минимуму и в крайнем случае ограничивался запуском СУБД и такому виду запросов как вставка, правка и удаление, так как они все же требуют непосредственного взаимодействия с физическим файлом БД из за требуемой его модификации.. .

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

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