В настоящее время я создаю веб-приложение, которое позволяет пользователям хранить и обмениваться файлами размером от 1 до 10 МБ.
Мне кажется, что хранение файлов в базе данных значительно замедлит доступ к базе данных.
Это действительная проблема? Лучше ли хранить файлы в файловой системе и сохранять имя файла и путь в базе данных? Есть ли рекомендации по хранению файлов при работе с базой данных?
Я работаю в PHP и MySQL для этого проекта, но эта проблема одинакова для большинства сред ( Ruby on Rails , PHP , .NET ) и баз данных (MySQL, PostgreSQL ).
database
database-design
mysql
file-handling
Б Семерка
источник
источник
10MB
такой большой в современной системе.Ответы:
Причины в пользу хранения файлов в базе данных:
Причина против хранения файлов в базе данных:
FILESTREAM
объект SQL Server, и вам необходимо перейти на другую систему базы данных.ИМО, считая хранение файлов в базе данных или нет как «плохое», требует больше информации об обстоятельствах и требованиях. Размер и / или количество файлов всегда будут маленькими? Нет ли планов использовать облачное хранилище? Будут ли файлы размещены на веб-сайте или в двоичном исполняемом файле, например, в приложении Windows?
В целом, мой опыт показал, что хранение путей обходится бизнесу дешевле, даже если учесть отсутствие ACID и вероятность сирот. Тем не менее, это не означает, что Интернет не легион с историями об отсутствии контроля ACID с ошибками в хранении файлов, но это означает, что в целом такое решение легче построить, понять и поддерживать.
источник
Во многих случаях это плохая идея. Это раздувает файлы базы данных и вызывает несколько проблем с производительностью. Если вы поместите капли в таблицу с большим количеством столбцов, это будет еще хуже.
Тем не мение! Некоторые базы данных, такие как SQL Server, имеют тип столбца FILESTREAM. В этом случае ваши данные фактически хранятся в отдельном файле на сервере базы данных, и в таблице сохраняется только идентификатор файла. В этом случае я не вижу особой причины не хранить данные на сервере SQL. Файлы автоматически включаются как часть резервной копии сервера, а база данных и файлы никогда не синхронизируются. Проблема с предложением Тони хранить имена файлов заключается в том, что база данных и файловая система могут быть не синхронизированы. База данных будет утверждать, что файл существует, когда он был удален на диске. Если процесс изменяет базу данных, а затем происходит сбой, файлы и база данных не будут совпадать (т. Е. Нет ACID с файлами вне базы данных).
источник
Да, это плохая практика.
Влияние производительности на БД:
SELECT
с любым столбцом BLOB, вы всегда будете осуществлять доступ к диску, в то время как без BLOB у вас будет возможность получать данные прямо из ОЗУ (БД с высокой пропускной способностью будет оптимизирована для размещения таблиц в ОЗУ);Преимущество в скорости - нет ! В то время как некоторые старые файловые системы не справляются с хорошими каталогами с миллионами файлов, большинство современных вообще не имеют проблем и фактически используют структуры данных того же типа, что и BD (обычно B-деревья). Например, ext4 (файловая система Linux по умолчанию) использует Htree .
Вывод: это снизит производительность вашей БД и не улучшит производительность поиска файлов.
Кроме того, поскольку вы говорите о веб-приложении - подача статических файлов непосредственно из файловой системы с использованием современного веб-сервера, которая может выполнять
sendfile()
syscall, является огромным улучшением производительности. Это, конечно, невозможно, если вы извлекаете файлы из БД. Рассмотрим, например, этот тест , показывающий, что Ngnix выполняет 25K запросов / с с 1000 одновременных подключений на ноутбуке нижнего уровня. Такая нагрузка поджарит любую БД.источник
Я был бы прагматичен в этом и следовал бы принципу «пока не оптимизировать». Сделайте решение, которое имеет смысл на данный момент, и такое, которое у вас есть ресурсы для разработки, чтобы правильно реализовать. Есть много потенциальных проблем . Но они не обязательно становятся реальными проблемами. Например, это не будет проблемой, если у вас есть 100 пользователей. Это может быть проблемой, если у вас есть 100 000 или 10 000 000 пользователей. Но в последнем случае должна быть основа для увеличения ресурсов на разработку для решения всех вопросов.
Но хранение данных в базе данных освобождает вас от решения других проблем, например, где следует хранить файлы, как их резервировать и т. Д. Поскольку вы пишете веб-приложение, это будет очень хорошая идея по соображениям безопасности. чтобы убедиться, что процесс, в котором размещено приложение, не имеет доступа на запись в файловую систему, вам необходимо настроить сервер таким образом, чтобы процесс имел доступ на чтение / запись к папке, в которой хранятся данные.
Я бы лично решил хранить данные в базе данных, но следите за тем, чтобы BLOBS не читались до тех пор, пока они действительно не потребуются, т.е. не выполнялось «SELECT * FROM ...» в тех таблицах, содержащих блоги. И я бы позаботился о том, чтобы дизайн облегчал перемещение данных из базы данных в файловую систему, если у вас возникают проблемы с производительностью. Например, храните информацию о файле в отдельной таблице файлов , таким образом сохраняя информацию о файле отдельно от других бизнес-объектов.
Предполагая, что у вас есть класс File для представления файла, считываемого в базе данных, влияние последующего перемещения на код будет минимальным.
источник
Microsoft выпустила официальный документ об этом несколько лет назад. Он концентрируется на SqlServer, но там вы можете найти некоторую интересную информацию:
Очень краткая версия их заключения:
Я бы порекомендовал вам написать несколько небольших тестов для вашего конкретного случая использования. Имейте в виду, что вы должны остерегаться эффектов кэширования. (Я был поражен, когда впервые получил скорости сохранения на диск, которые, казалось, имели более высокую пропускную способность, чем это было физически возможно!)
источник
Старая традиционная мудрость хранения файлов вне базы данных может больше не действовать. В принципе, я бы предпочел целостность, а не скорость, и с современной СУБД вы можете иметь и то, и другое.
Том Кайт, кажется, согласен :
источник
Да.
Если вы обслуживаете файл из вашей файловой системы, ваш веб-сервер может использовать код ядра, такой как sendfile () в BSD или Linux, чтобы скопировать файл непосредственно в сокет. Это очень быстро и очень эффективно.
Обслуживание файлов из базы данных означает, что вам необходимо скопировать данные с диска сервера базы данных в память сервера базы данных, затем из памяти сервера базы данных в сетевой порт сервера базы данных, затем из сети в процесс веб-сервера, а затем снова в базу данных сервера. исходящее сетевое соединение.
Если у вас нет веской причины не делать этого, всегда лучше обслуживать статические файлы из файловой системы.
источник
Знаменитый Том Кайт написал, что они (Oracle) используют базу данных Oracle в качестве файлового сервера, и она прекрасно работает, даже быстрее, чем обычная файловая система, с полной транзакционностью, без потери производительности и с одним резервным копированием.
Да, но обратите внимание, что они являются производителем БД Oracle, и для любого другого пользователя существуют проблемы с ценами. Использование коммерческих БД, таких как Oracle, для хранения файлов просто неэффективно с точки зрения затрат.
Однако, например, в PostgreSQL вы можете просто запустить другой экземпляр БД только для хранения больших двоичных объектов. У вас есть полная поддержка транзакций. Но транзакционность стоит пространства БД. Существует необходимость в базе данных для хранения нескольких экземпляров BLOB-объектов для нескольких одновременных транзакций. В PostgreSQL это наиболее болезненно, поскольку в этой базе данных хранятся дубликаты BLOB-объектов, созданных для транзакции, даже если они больше не нужны, пока не будет завершен процесс VACUUM.
С другой стороны, с хранилищем файловой системы вы должны быть очень осторожны, когда кто-то изменяет файл, потому что транзакцию можно откатить, и копия файла должна храниться до тех пор, пока старая версия больше не будет видна.
В системе, где файлы только добавляются и удаляются, а транзакционный доступ к файлам не является проблемой, хранилище файловой системы будет ИМХО лучшим выбором.
источник
Обычно лучше хранить большие большие двоичные объекты в отдельной таблице и просто сохранять ссылку на внешний ключ для большого двоичного объекта в основной таблице. Таким образом, вы все равно можете извлечь файл из базы данных (поэтому вам не нужен какой-либо специальный код), и вы избежите проблем, связанных с зависимостями от внешних БД (синхронизация БД и файловой системы и т. Д.), Но вы только понесете эти издержки. если вы явно присоединитесь к этой таблице (или сделаете отдельный вызов). 10 МБ не очень большие, у большинства современных коммерческих баз данных проблем не будет. Единственная причина, по которой я бы сохранил файл в файловой системе - это сокращение пропускной способности базы данных. Если ваша база данных будет перетасовывать много этих файлов, то вам может потребоваться разделить рабочую нагрузку и сохранить только дескриптор файла какого-либо типа. Затем вы можете сделать отдельный вызов для загрузки файла с другого сервера,
источник
Вы можете столкнуться с некоторыми из этих проблем:
SELECT *
которое включает в себя строку с большим BLOB-объектом, занимает очень много времени, даже если вам не нужен BLOB-объект (Конечно, вы должны сделать определенный выбор, но иногда приложения пишутся так)Конечно, вы также получаете некоторые преимущества:
Лично я не делаю это, поскольку нахожу минусы намного тяжелее, чем плюсы. Но, как указано выше, это полностью зависит от вашего варианта использования и тому подобное.
источник
Некоторые системы управления контентом Enterpirse, такие как SiteCore, используют одну базу данных для хранения данных страницы и другую базу данных для хранения файлов. Они используют MS SQL Server.
источник
Для практической реализации, вот что вы можете касаться:
ПРЕИМУЩЕСТВА:
Недостатки:
источник