Должен ли я использовать MySQL тип поля blob?

Я изо всех сил пытаюсь решить, должен ли я использовать тип поля блоба MySQL в моем предстоящем проекте.

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

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

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

Есть ли снижение производительности при использовании типа поля MySQL blob? Я обеспокоен выбором решения, которое будет препятствовать дальнейшему росту веб-сайта, а также выбором решения, которое будет нелегко поддерживать.

7 ответов

Решение

Если ваш веб-сервер будет обслуживать эти загруженные файлы через Интернет, производительность почти наверняка будет лучше, если они будут храниться в файловой системе. После этого веб-сервер сможет применять подсказки кэширования HTTP, такие как Last-Modified а также ETag что повысит производительность для пользователей, обращающихся к одному и тому же файлу несколько раз. Кроме того, веб-сервер автоматически установит правильный Content-Type для файла при подаче. Если вы храните BLOB-объекты в базе данных, вы в конечном итоге реализуете вышеупомянутые функции и многое другое, когда вам нужно будет получить их бесплатно с вашего веб-сервера.

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

Я бы придерживался обычной практики хранения файлов в файловой системе и пути к файлу в базе данных.

Есть ли снижение производительности при использовании типа поля MySQL blob?

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

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

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

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

Если вы используете файловую систему, а не BLOB-объект, тогда возникает вопрос: вы заставляете веб-сервер обслуживать его, указывая псевдоним на папку?

  • + супер быстро
  • + хорошо кэширует
  • - дополнительная конфигурация сервера: виртуальный каталог; необходимо соответствующее расширение файла, чтобы вернуть желаемое Content-Type
  • - дополнительная конфигурация сервера: нужно добавить Content-Disposition: attachment/X-Content-Type-Options заголовки, чтобы остановить анализ кода IE для HTML как часть мер против XSS

или вы обслуживаете файл вручную, выполняя сценарий на стороне сервера, выполняя его, как если бы вы работали с большим двоичным объектом MySQL?

  • - потенциально медленный
  • - для правильного кеширования требуется немало ручной обработки If-Modified-Since и ETag
  • + может использовать собственные методы контроля доступа приложения
  • + легко добавить правильные заголовки Content-Type и Content-Disposition из обслуживающего скрипта

Это компромисс, на который не существует единого общепринятого ответа.

По моему опыту, сохранение BLOB в MySQL - это нормально, пока вы храните только BLOB в одной таблице, а другие поля находятся в другой (объединенной) таблице. И наоборот, поиск в полях таблицы с несколькими стандартными полями и одним полем большого двоичного объекта со 100 МБ данных может значительно замедлить запросы.

Мне пришлось изменить слой данных почтового приложения для этой проблемы, где электронные письма хранились с содержимым в той же таблице, что и дата отправки, адреса электронной почты и т. Д. Для поиска 10000 электронных писем потребовалось 9 секунд. Теперь он берет то, что должен;-)

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

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

Многие люди рекомендуют не хранить вложения файлов (обычно это относится к изображениям) в BLOB-объектах в базе данных. Вместо этого они предпочитают хранить путь в виде строки в базе данных и хранить файл в безопасном месте в файловой системе. В этом есть некоторые достоинства:

  • База данных и резервные копии базы данных меньше.
  • Редактировать файлы в файловой системе проще, если вам нужно работать с ними ad hoc.
  • Файловые системы хороши для хранения файлов. Базы данных хороши для хранения кортежей. Пусть каждый делает то, что у него хорошо получается.

Также есть контраргументы, которые поддерживают размещение вложений в BLOB-объектах:

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

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

Я знаю, что вы пометили свой вопрос MySQL, но если люди, читающие этот вопрос, используют другие бренды СУБД, они могут захотеть изучить BFILE при использовании Oracle, или FILESTREAM при использовании Microsoft SQL Server 2008. Они дают вам возможность хранить файлы вне базы данных, но получать к ним доступ, как если бы они были частью строки в таблице базы данных (более или менее).

Большие объемы данных в конечном итоге отразятся на производительности. MS SQL 2008 имеет специализированный способ хранения двоичных данных в файловой системе:

http://msdn.microsoft.com/en-us/library/cc949109.aspx

Я бы тоже использовал подобный подход для вашего проекта.

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

На мой взгляд, хранение файлов в базе данных - плохая идея. То, что вы можете хранить, это id, имя, тип, возможно, md5 хеш файла и дата вставки. Файлы могут быть загружены в папку вне общедоступного места. Также вы должны быть обеспокоены тем, что не рекомендуется хранить более 1000 файлов в одной папке. Так что вам нужно создавать новую папку каждый раз, когда идентификатор файла увеличивается на 1000.

Другие вопросы по тегам