it-roy-ru.com

PHP хранить изображения в MySQL или нет?

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

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

Кроме того, я пытался выяснить, лучше ли хранить изображение в таблице users MySQL как большой двоичный объект или, возможно, в отдельной таблице images с уникальным идентификатором, и просто сохранить соответствующий идентификатор изображения в таблице users, или просто сохраните загруженный файл на сервере (также через страницу загрузки) и сохраните файл как theUsersUniqueUsername.jpg. Лучший вариант?

Я нашел руководство по сохранению изображений в MySQL здесь: http://www.phpriot.com/articles/images-in-mysql

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

31
occhiso

Всегда зависит от контекста, но обычно я храню изображение пользователя в файловой системе в папке с именем /content/user/{user_id}.jpg и стараюсь как можно меньше беспокоить базу данных.

40
Mario

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

Проверьте этот ответ тоже:

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

23
Philip Morton

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

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

  • Не храните абсолютный URL-адрес файла в вашей БД, только уникальную часть (и, возможно, одну или две папки), например, 2009/uniqueImageName.jpg или просто uniqueImageName.jpg. Затем на своих страницах просто добавьте хост и другие папки вперед, чтобы у вас была некоторая гибкость при перемещении изображений - все, что вам нужно изменить, - это строка или две в вашем PHP/Страница ASP.NET.

  • Для безопасности не нужно хранить вне корневого каталога документа - файл .htaccess с DENY FROM ALL будет работать так же и обеспечит большую гибкость

  • Не нужно так много «шунтировать» изображения для безопасности, просто есть страница getImage.php или что-то еще, а затем вместо вставки фактического URL-адреса в srcimage используйте что-то вроде getImage.php?file=uniqueImageName.jpg. Затем файл getImage.php может проверить, пользователь авторизован и получает изображение (или нет).

  • Используйте имя, которое гарантированно будет уникальным (предпочтительно целое число, то есть первичный ключ) при хранении, некоторые файловые системы (например, Windows) нечувствительны к регистру, поэтому JoeBloggs.jpg и joebloggs.jpg уникальны для базы данных, но не для файловой системы поэтому один перезапишет другой.

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

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

17
Joseph Earl

Оспаривание традиционной мудрости!

Конечно, это зависит от контекста, но у меня есть очень большое приложение с тысячами изображений и документов, хранящихся в виде BLOBS в базе данных MySQL (средний размер = 2 МБ), и приложение отлично работает на сервере с 256 МБ памяти. Секрет правильной структуры базы данных. Всегда сохраняйте две отдельные таблицы, одна из которых хранит основную информацию о файле, а другая должна просто содержать большой двоичный объект и первичный ключ для доступа к нему. Все базовые запросы будут выполняться к таблице сведений, а к другой таблице доступ осуществляется только тогда, когда файл действительно необходим, и доступ к нему осуществляется с помощью индексированного ключа, поэтому производительность чрезвычайно высока. 

Преимущества хранения файлов в базе данных многочисленны:

  1. Требуются гораздо более простые системы резервного копирования, поскольку вам не нужно выполнять резервное копирование файловой системы.
  2. Управлять безопасностью файлов гораздо проще, так как вы можете проверить их перед выпуском двоичного файла (да, вы можете сохранить файл в непубличном каталоге и сделать так, чтобы скрипт прочитал и отрыгнул файл, но производительность не будет заметно выше. 
  3. (Аналогично # 1). Он четко разделяет «пользовательский контент» и «системный контент», упрощая миграцию и клонирование.
  4. Проще управлять файлами, отслеживать/хранить изменения версий и т.д., Поскольку для добавления элементов управления версиями требуется меньше модификаций скриптов.

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

В любом случае, очевидно, что FS хорошо работает во многих случаях, но лично я считаю, что управление БД намного проще и более гибко, и, если его правильно написать, потери производительности крайне малы.

16
Ben D

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

Несмотря на то, что кажется привлекательным хранить двоичные файлы в БД, выборка и манипулирование ими добавляет дополнительную сложность, которой можно избежать, просто сохраняя файлы в файловой системе и сохраняя пути/метаданные в БД.

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

10
Neil Aitken

Я недавно видел список этого совета: http://www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries

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

Так что просто сохраните путь к файлу изображения :)

9
AntonioCS

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

  1. Хранение файловой системы становится более сложным, когда ваши серверы приложений кластеризованы. Вы должны иметь общее хранилище. Даже если ваша текущая среда не является кластеризованной, это усложняет масштабирование в случае необходимости.
  2. В любом случае вы должны использовать CDN для статического контента и настроить приложение в качестве источника. Это означает, что ваше приложение будет поражено только один раз для данного изображения, затем оно будет кэшировано в CDN. CloudFront очень дешев и прост в настройке ... нет причин не использовать его. Сохраните пропускную способность для вашего динамического контента.
  3. Гораздо быстрее (и, следовательно, дешевле) разрабатывать сохраненные изображения в базе данных.
  4. Вы получаете ссылочную целостность с сохраненными изображениями базы данных. Если вы храните изображения в файловой системе, у вас неизбежно будут файлы-сироты без соответствующих записей в базе данных, или у вас будут записи в базе данных с неработающими файловыми ссылками. Это БУДЕТ ... это просто вопрос времени. Вам придется написать что-нибудь, чтобы очистить их.

В любом случае, мои два цента.

6
Dustin
  1. Для чего вообще нужен тип данных blob, если не для хранения файлов?
  2. Если ваше приложение требует авторизации до доступа к файлам, изменения заключаются в том, что вы а) храните файлы вне DOCUMENT_ROOT (чтобы к ним нельзя было получить прямой доступ, и, возможно, б) отправляете все содержимое файлов через приложение (конечно, возможно, вы делаете что-то вроде временного перехода к хэшированию, но общедоступного имени файла). Таким образом, накладные расходы памяти все равно есть, и вы также можете получать данные из базы данных.
  3. Если вам необходимо хранить файлы в файловой системе, выполните действия, предложенные выше Андреасом, и присвойте им имена, используя то, что вы уже знаете (т.е. первичный ключ соответствующей таблицы).
4
Sam Wilson

Я думаю, что большинство механизмов баз данных уже настолько продвинуты, что хранение BLOB-данных не имеет никаких недостатков (раздутая база данных и т.д.). Одним из преимуществ является то, что у вас нет битых ссылок, когда изображение уже находится в базе данных. При этом я сам всегда делал так, чтобы я сохранял файл на диске и передавал URI в базу данных. Это зависит от использования. Может быть проще обрабатывать img-in-db, если страница очень динамична и часто меняется - без проблем с пространством имен. Я должен сказать, что все заканчивается тем, что вы предпочитаете.

2
Jens Jansson

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

например если у пользователя есть идентификатор 23, вы можете сохранить изображение на www.yourname.com/users/profile_images/23.jpg. Затем, чтобы отобразить, вы можете проверить, существует ли изображение, и отобразить его соответственно, в противном случае отобразить ваш общий значок.

2
Alec Smart

Как предложили другие:

  • Храните изображения в файловой системе
  • Не беспокойтесь о сохранении имени файла, просто используйте идентификатор пользователя (или что-нибудь еще, что «вы уже знаете»)
  • Поместите статические данные на другой сервер (даже если вы просто используете «static.yourdomain.com» в качестве псевдонима вашего обычного сервера)

Зачем ?

Чем больше ваша база данных, тем медленнее она будет . Хранение вашего изображения в базе данных увеличит размер вашей базы данных . Сохранение имени файла увеличит размер вашей базы данных.

Размещение статических данных на другом сервере (псевдоним):

  • Делает масштабирование намного проще
  • Большинство браузеров не будут отправлять более двух запросов на один сервер, размещая статические данные на «втором» сервере, вы ускоряете загрузку
2
Andreas

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

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

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

Проверьте этот реальный пример, все еще находящийся в разработке, на хосте SHARED, используя MVC: http://www.gt8.com.br/salaodocalcado/calcados/meia-pata/

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

Я провел несколько тестов на выделенном сервере, и результаты превзошли все ожидания.

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

1
user2377782

В моем случае я храню файлы в файловой системе . В моей папке с изображениями я создаю новую папку для каждого элемента с именем на основе идентификатора элемента (строка из БД). И назовите изображения в порядке, начиная с 0. Так что, если у меня есть таблица с именем Предметы, как это:

       Items      
|-----|------|-----|
| ID  | Name | Date|
|-----|------|-----|
| 29  | Test1| 2014|
|-----|------|-----|
| 30  | Test2| 2015|
|-----|------|-----|
| 31  | Test3| 2016|
|-----|------|-----|

мой каталог изображений выглядит примерно так: 

images/
      29/
      30/
      31/


images/29/0.png
images/29/1.jpeg
images/29/2.gif

и т.п.

0
Elnoor

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

0
Lucacri

Это плюсы обоих решений

В BLOBS:

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

2) Резервные копии БД также будут исчерпывающими

В файлах

1) Удобное собственное кэширование (и это упущение в предыдущих комментариях, с обновлением и заголовками, которые вам не придется перепроектировать в БД (БД не обрабатывают время последней модификации по умолчанию)

2) Легкость изменения размеров позже

3) Простота модерации (просто зайдите в свои папки, чтобы проверить, все ли правильно)

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

0
Irem

Только что проверил мой img как blob. Это решение работает медленнее, чем изображения на сервере в виде файла. Время загрузки должно быть одинаковым с изображениями из БД или http, но это не так. Зачем? Я уверен, что когда изображения являются файлами на сервере, браузер может кэшировать их и загружать только один раз, в первый раз. Когда образ собирается из БД, каждый раз загружается снова. Это мое мнение. Возможно, я ошибаюсь в кэшировании браузера, но работаю медленнее (blob). Sry мой английский, что угодно; P

0
Dudeist