Чи потрібно зберігати зображення в моїй базі даних або файловій системі в цьому додатку?

Я використовую ASP.NET MVC 4 і SQL Server 2012. У мене немає проблем, що йдуть на будь-який з цих рішень, але я хочу знати, який буде краще підходити в конкретному додатку я створюю зараз.

Я роблю своєрідне застосування бібліотечної системи. Єдині зображення, які зберігатиметься в програмі:

  • Фотографії профілю користувачів (1 на користувача)
  • Фотографії профілю бібліотек (1 за бібліотеку)
  • Книга авторів (1 автор)
  • Книга обкладинки книги (1 за книгу)

Жодне з збережених зображень не повинно бути високої якості. Очевидно, що зображення не є великою частиною програми, і, враховуючи це, я зараз зберігаю зображення у своїй базі даних. Хоча я помітив щось, що, на мою думку, робить для великого кон.

Зображення витягуються за допомогою Url.ActionLink , що призводить до способу дії контролера, який приймає (наприклад) параметр bookId, перш ніж досягати бази даних, отримуючи зображення цієї книги і відсилаючи її назад. Отже, якщо користувач шукає книги, і він отримує список книг разом зі своїми зображеннями перед ним, з'явиться новий заклик до способу дії, який витягує зображення та новий запит до бази даних для кожного переліченого зображення.

Чи є кращий спосіб вирішення цього? Чи варто переглядати збереження своїх зображень у базі даних, або це не є великою проблемою?

EDIT: не розглядати це питання як дублікат, оскільки він стосується певного типу програми, яка обробляє дуже мало даних зображення, на відміну від будь-якого типу програми (наприклад, у зв'язане запитання ). Звичайно, коли ви не впевнені в тому, скільки зображень ви збираєтеся зберігати, завжди краще зберігати зображення у файловій системі. Це не такий випадок. Характер відповідей тут і відповіді на це свідчить.

9
Перевага використання зображень у файловій системі полягає в тому, що ви можете обслуговувати їх з окремого вікна з деяким більш легким (а отже і швидшим) сервером, таким як nginx або lighttpd. Але, звичайно, це відкриває можливості для проблем послідовності.
додано Автор Vali Hutchison, джерело
Чи розглядали ви базу даних NoSQL для цієї мети? Можливо, ви зможете використовувати базу даних , яка ефективно обробляє цей тип даних, що дозволить ви повинні дотримуватися запитів, а не змішувати доступ до файлів.
додано Автор user22815, джерело
@Snowman Я думаю, що NoSQL дійсно є надмірним для цієї програми. Враховуючи, що я використовую EF6, це тільки зробить доступ до даних більш складним для мене.
додано Автор Alternatex, джерело

5 Відповіді

Чому б не зробити обох? База даних - це резервна, кінцева сховище для зображення. Публічна сторона може бути простим читанням з db, але ви можете легко розширити її в кеш-диску для читання, а також скористатися численними прийомами інфраструктури, щоб краще підвищити продуктивність.

Перемоги тут:

  • simpler data backup -- database backups are fun and easy, no file system touching necessary
  • simpler dev story -- you don't need to handle a bunch of files, just get the dev team a copy of the database
  • easier to write the image -- file systems are a PITA, from permissions, to changing locations from dev->qa->production, to contention to lack of transactions. If the writes are going to the db then you solve 90% of those problems.
  • modern databases can handle it -- presuming we are talking fairly typical image file sizes measuring under a few megabytes most modern database systems can handle them very well. It is not the database murdering issue that some older articles would have you believe.
8
додано
Дякую. Я не думав, що далеко вгору стек, але та ж ідея з кэш-дисками для читання може бути застосована і до CDN.
додано Автор Mark Gibaud, джерело
Виберу цей вибір як відповідь, але обидва відповіді були дійсно корисними у прийнятті мого рішення. Заохочуйте мене все ще розглядати можливість зберігання зображень у базі даних правильним методом зберігання.
додано Автор Alternatex, джерело

Отже, якщо користувач шукає книги, і він отримує список книг разом із зображеннями перед ним, з'явиться новий виклик методу дії, який витягує зображення та новий запит до бази даних для кожного зображення.

Я б сказав, що це хороша річ. Зображення займає набагато більше часу для передачі, ніж текст, тому замість того, щоб користувач очікував завантаження з БД, можна показати текст, а потім завантажити зображення окремо.

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

Однак слід розглянути можливість виділення зображень у їхній власній таблиці зображень. Не зберігайте зображення в тій же таблиці, що й книга; просто збережіть ідентифікатор зображення і використовуйте його для отримання зображення пізніше. Це набагато ефективніше, враховуючи спосіб управління базами даних на диску. Це твердження значно важливіше, якщо ви плануєте змінити зображення, пов'язане з книгою, у будь-який момент.

Нарешті, мій досвід роботи з цими речами полягає в тому, що ви дуже швидко зможете перейти до ситуації, коли ви хочете використовувати мережу доставки вмісту для зберігання зображень (див. AWS CloudFront або Azure CDN або CloudFlare), що дійсно є кращим з обох світів - додаткове сховище, до якого можна отримати доступ безпосередньо за допомогою URL-адреси, навіть не заважаючи вашому додатку - і не стільки додаткової роботи. Переміщення до CDN - це дуже легка зміна, якщо ви виділили свої зображення у свою таблицю.

Або, ви можете просто піти на рішення CDN зараз і ніколи не турбуватися про це знову.

4
додано
@EsbenSkovPedersen: "Перехід до CDN" - це "це" у реченні, яку ви цитуєте ... можливо, я повинен редагувати цю лінію.
додано Автор fluffels, джерело
"Це дуже легка зміна, якщо ви виділяєте свої зображення в їхній власний стіл". Що це стосується CDN?
додано Автор mkuse, джерело
Я хочу сказати, що перехід до CDN - це легка зміна, незалежно від того, де ви зберігаєте свої зображення.
додано Автор mkuse, джерело

З обох боків дискусії є вагомі побоювання, тому завжди враховуйте ваші вимоги та обмеження. Скільки даних, скільки зображень, наскільки велика, наскільки безпечна, час відновлення?

Вбудоване/BLOB-пам'ять

Вгору

  • Контроль версій/послідовність транзакцій. Це ключова смислова різниця. Це добре обробляється БД, тому дозволяє відновити точку в часі. Файлові системи цього не надають, тому ви не матимете можливості відкочуватися. (Я не маю на увазі автономну файлову систему, я маю на увазі проблему контролю транзакцій з вашого коду). Зображення та документи можуть бути пошкоджені помилкою користувача або не синхронізовані, перетворюючись на 2-фазну проблему. Деякі системи вирішують це, додаючи зовнішню систему контролю версій, але вона потребує інтеграції.
  • спрощує реалізацію
  • Автономні всі дані про додатки - спрощує процес резервного копіювання та відновлення або міграції системи доти, доки відбиток даних блога не є громіздким; просто зробіть дамп, резервне копіювання, експорт (незалежно від терміну для вашого смаку DB) і перемістіть його до нової бази даних. Немає зовнішніх файлів для синхронізації.
  • Безпека/контроль доступу є більш чистим; доступ до зображення BLOB є властивим доступу до рядка даних. Якщо документ знаходиться за межами БД і ми дозволяємо HTTP-серверу витягувати його (за межами програми MVC), це може бути краще для паралелізму і масштабованості, але приділяє більше уваги, щоб авторизація застосовувалася до зовнішніх файлів, оскільки вони є БД даних. Я перевірив проекти, де великі файли зберігалися поза рядком, під статичними, мультиплексованими URL-адресами, і мій перший сценарій тестування полягав у спробі прямого доступу до статичної URL-адреси без аутентифікації. Якщо ви займаєтеся безпечними документами за межами БД, не обслуговуйте їх статично, і переконайтеся, що ваша політика безпеки охоплює контроль доступу до зображень між орендарями. Аутентифікація вашого HTTP-сервера повинна інтегруватися з аутентифікацією всієї системи. Це викликає велике занепокоєння в базах даних з декількома орендарями. Менше занепокоєння в єдиних системах з однією метою, з простою аутентифікацією.
  • Зменшена площа поверхні сервера баз даних - у багатьох системах БД відокремлена від сервера додатків, і між ними є брандмауер. Все можна подавати через один порт DB (1433/MSSQL) або (1521/Oracle) як приклад. Якщо ви переміщуєте БД на окремий рівень, вам слід скористатися NFS або NAS або скопіювати файли між сервером додатків, якщо їх масштабувати.

Зворотна сторона

  • Час резервного копіювання - для дійсно великих баз даних (не застосовується до вас) резервне копіювання та відновлення стає неприємним і починає ставати проблематичним і дорогим; у той час як у вас може бути невеликий набір даних ядра, ви можете мати багато ГБ або ТБ даних зображення. Розглядаючи все це як одну послідовну базу даних, це добре і з точки зору цілісності, але погано для резервного копіювання і відновлення, якщо ви не використовуєте СУБД з корпоративним резервним кодом та відновленням (наприклад, Oracle RMAN та копіювання резервних копій, EMC BCV або знімки Netapp). У одного клієнта, наша БД стала настільки великою, що ми просто перестали підтримувати її і віддавали перевагу географічним реплікам. Інший відомий випадок був Starbucks (адміністратори баз даних розмістили цей документ в Інтернеті, цікаво прочитати, якщо ви в цьому).
  • Час до відновлення (так званий час відновлення або SLA) - це часто визначається клієнтом. Як DBA ви повинні повернутися в це, якщо клієнт вже заявив про це. Якщо додавання 90% до розміру бази даних для зберігання незахищених зображень впливає на SLA критичних даних, то не робіть цього.
  • Менша гнучкість. Непростий доступ до документів з утилітами рівня ОС, команд оболонки і т.д.

Особисто, в цьому контексті, я думаю, що ваги укладаються на користь вбудованого сховища БД. Якщо ваша БД не велика, зберігайте її все в БД.

4
додано
Для редагування версій файлової системи, ви можете шукати zfs, або вважаєте, що git також є файлом типу.
додано Автор user40980, джерело
@MichaelT Звичайно, я знаю все про них і використовували обидва, серед інших варіантів, як VxFS/VxLVM. Вони забезпечують справжню користь. Але вони все ще зовнішні до БД. Ви повинні інтегрувати їх, якщо ви хочете загальну транзакційну послідовність і контроль перегляду. Зберігаючи, що в синхронізації з транзакцією бази даних є 2-фазова проблема фіксації. Іншими словами, ви не можете легко "зробити або відкотити" ZFS як частину загальної транзакції бази даних.
додано Автор Sebastian, джерело

Раджу не зберігати зображення в базі даних.

База даних не призначена для використання - це не реляційні дані, що стосуються інших даних. Вона легко займає величезний простір і важко маніпулювати, коли знаходиться в колонці бази даних.

I use databases to store the name, timestamps, meta data and file location. I then store and access the image at that file location/name

Я пройшов через це кілька років тому в реальному світі і разом з багатьма іншими прийшов до висновку, що зберігання зображень в базі даних було поганим підходом. Для версій і історії просто є код з посиланнями в керуванні джерелами і керувати ними як з будь-яким іншим. Отже, змініть назву для кожного зображення, використовуйте штампи дати і не використовуйте повторно те саме ім'я файлу для іншого зображення.

Багато людей, які починають під час цього, повинні через деякий час перейти на основний комутатор. Це впливає на потреби в сховищах, серверах, процесорі і, можливо, мережевому трафіку. Це також ускладнює використання сховища файлової системи, заснованої на хмарі, яке може враховувати географічне розташування, трафік тощо. Ці методи стають критичними, коли ваша компанія зростає, а зображення в базі даних можуть сильно обмежити ваші можливості.

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

3
додано

Якщо ви використовуєте сервер sql (2008 рік або пізніше), ви можете зберігати їх у базі даних у вигляді крапель або за допомогою FILESTREAM. Як зазначали інші коментатори, я б не пішов з власністю зберігати файл на диск підхід, як вам доведеться керувати послідовністю в цьому сценарії.

Гарне посилання на FILESTREAM можна знайти тут:

Правила FileStream

Деякі загальні правила:

У SQL Server, BLOB можуть бути стандартними varbinary (max) даними, які зберігаються   дані в таблицях або файли FILESTREAM varbinary (max), які зберігаються   даних у файловій системі. Визначається розмір і використання даних   чи слід використовувати сховище бази даних або сховище файлової системи. Отже, в   Коротко кажучи, це типові сценарії, де ця функція найкраща   підходить:

     
      
  • Якщо ви зберігаєте BLOB із середнім розміром 1 Мб або   більше.
  •   
  • Коли швидкий доступ до читання є незмінним.
  •   
  • Коли ви повинні отримати доступ до BLOB-кодів з коду середнього рівня вашої програми.
  •   
     

Загалом, основними перевагами використання FILESTREAM над іншими параметрами є:

     
      
  • Зберігання та вилучення BLOB-повідомлень здійснюється разом з реляційними даними в одному   сховище даних.
  •   
  • Так, BLOB включені до резервних копій бази даних і відновлення.
  •   
  • Вставлення, оновлення та видалення BLOB і реляційних даних відбувається в одній транзакції бази даних.
  •   
  • Максимальний розмір 2 ГБ для стовпця varbinary (max) не застосовується; Ви обмежені лише наявним простором файлової системи NTFS.
  •   
  • Пам'ять пулу буферів SQL Server не використовується для роботи на BLOB; у попередніх версіях великі BLOB можуть споживати багато цієї пам'яті.
  •   
  • Весь доступ BLOB може бути виконаний з коду .NET, дозволяючи вашому коду середнього рівня легко працювати з цими об'єктами.
  •   
  • Файлова система NTFS може зберігати та отримувати великі BLOB-файли більш ефективно, ніж SQL Server.
  •   
     

Проте для реалізацій FILESTREAM застосовуються деякі обмеження:

     
      
  • Функція FILESTREAM не підтримується з відображенням баз даних.
  •   
  • Контейнери даних FILESTREAM не можуть спільно використовувати один і той же каталог або вкладатись.
  •   
  • Дані FILESTREAM не зашифровані, навіть якщо включено прозоре шифрування даних (TDE).
  •   
2
додано
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug