Чи погана практика зберігання великих файлів (10 Мб) у базі даних?


188

Зараз я створюю веб-додаток, який дозволяє користувачам зберігати та обмінюватися файлами розміром 1 Мб - 10 Мб.

Мені здається, що зберігання файлів у базі даних значно уповільнить доступ до бази даних.

Це поважне питання? Чи краще зберігати файли у файловій системі та зберігати ім’я та шлях файлів у базі даних? Чи є найкращі практики щодо збереження файлів під час роботи з базою даних?

Я працюю в PHP та MySQL для цього проекту, але проблема однакова для більшості середовищ ( Ruby on Rails , PHP , .NET ) та баз даних (MySQL, PostgreSQL ).


9
Питання, пов'язані на DBA.SE: Файли - у базі даних чи ні?
Нік Чаммас

11
Здивовано, що ніхто не опублікував дослідження MS, зроблені з цього питання (для SQL Server 2008): до BLOB чи не до BLOB: велике сховище об’єктів у базі даних або у файловій системі
Oded

2
великий - відносна кількість, я (і, мабуть, багато інших) не вважаю 10MBтакою великою в сучасній системі.

27
Це тематично відповідно до FAQ - воно вписується під кулі "дизайнерські шаблони" (косо-антишаблони) та "архітектура програмного забезпечення". Чому його закрили?
Ізката

21
Я не бачу жодної розпливчастості у питанні, як зараз. Я поняття не маю, чому його закрили.
reinierpost

Відповіді:


139

Причини на користь зберігання файлів у базі даних:

  1. Консистенція ACID, включаючи відкат оновлення, що ускладнюється, коли файли зберігаються за межами бази даних. Це не слід блискавити злегка. Синхронізація файлів та бази даних та можливість брати участь у транзакціях може бути дуже корисним.
  2. Файли передаються в базу даних, і з неї неможливо осиротіти.
  3. Резервні копії автоматично включають файли бінарних файлів.

Причина збереження файлів у базі даних:

  1. Розмір двійкового файлу відрізняється між базами даних. Наприклад, на SQL Server, коли не використовується об'єкт FILESTREAM, він становить 2 Гб. Якщо користувачам потрібно зберігати файли більше (наприклад, фільм), вам доведеться перестрибувати обручі, щоб ця магія відбулася.
  2. Збільшує розмір бази даних. Одне загальне поняття, яке вам слід прийняти до серця: Рівень знань, необхідний для ведення бази даних, збільшується пропорційно розміру бази даних.Тобто великі бази даних є більш складними в обслуговуванні, ніж невеликі. Зберігання файлів у базі даних може зробити базу даних значно більшою. Навіть якщо скажімо, щоденного повного резервного копіювання було б достатньо, з більшим розміром бази даних, ви, можливо, більше не зможете цього зробити. Можливо, вам доведеться розглянути можливість розміщення файлів у іншій групі файлів (якщо база даних підтримує це), підключіть резервні копії, щоб відокремити резервну копію даних від резервної копії файлів тощо. Нічого з цих речей неможливо вивчити, але зробіть додати складність у обслуговуванні, що означає витрати на бізнес. Більші бази даних також споживають більше пам'яті, оскільки вони намагаються заповнити якомога більше даних у пам'ять.
  3. Переносність може викликати занепокоєння, якщо ви використовуєте особливості системи, такі як FILESTREAMоб'єкт SQL Server, і вам потрібно перейти на іншу систему баз даних.
  4. Код, який записує файли в базу даних, може бути проблемою. Одна компанія, з якою я консультувався не так багато місяців тому в якийсь момент, підключив інтерфейс Microsoft Access до їх сервера баз даних і використовував можливість Access завантажувати що завгодно, використовуючи його управління Ole Object. Пізніше вони змінилися, щоб використовувати інший контроль, який досі покладався на Оле. Набагато пізніше хтось змінив інтерфейс для зберігання необробленого бінарного файлу. Видобуток цих Оле-об'єктів був новим рівнем пекла. Коли ви зберігаєте файли у файловій системі, не існує додаткового шару, щоб обернути / налаштувати / змінити вихідний файл.
  5. Складніше подавати файли на веб-сайт. Для того, щоб зробити це за допомогою бінарних стовпців, вам потрібно написати обробник для передачі бінарного файлу з бази даних. Ви також можете це зробити, навіть якщо ви зберігаєте шляхи до файлів, але цього не потрібно робити. Знову ж таки, додавання обробника не є неможливим, але додає складності та є ще одним моментом відмови.
  6. Ви не можете скористатися хмарним сховищем. Припустимо, одного дня ви захочете зберігати свої файли у відрі Amazon S3. Якщо ви зберігаєте в базі даних файлові шляхи, вам надається можливість змінити їх на шляхи на S3. Наскільки мені відомо, це неможливо в будь-якому сценарії з будь-якою СУБД.

ІМО, вважаючи збереження файлів у базі даних чи не "поганим", вимагає додаткової інформації про обставини та вимоги. Чи завжди розмір та / або кількість файлів буде невеликим? Чи не планується використовувати хмарне сховище? Чи подаватимуться файли на веб-сайті або у двійковому виконуваному файлі, як програма Windows?

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


Чому не можна використовувати CDN? Це підтримуваний сценарій, в якому майже кожен CDN я чув.
Біллі ONeal

@BillyONeal - Ви не можете використовувати CDN та зберігати файл у базі даних. Якщо ви не в порядку з дублюванням, ви не можете мати обох.
Томас

3
Ем, вся точка CDN - це дублювання. CDN просто кешують ціль веб-адреси - єдина вимога, щоб хост HTTP обслуговував вміст і вміст змінювався рідко. (Як, на землі, CDN повинен повідомити, звідки ви все-таки витягнули зображення?)
Біллі ONeal

3
@BillyONeal - Однак, я думаю, що це поганий вибір слів з мого боку, і я скоригував свою відповідь. Зокрема, якщо ви хочете використовувати хмарний накопичувач (а потім, можливо, використовувати CDN зі своїм хмарним сховищем), ви не можете це робити на самому місці за допомогою рішення для зберігання бази даних. Вам доведеться написати процедуру синхронізації, щоб витягнути файли з бази даних, а потім надіслати їх своєму постачальнику хмарних сховищ.
Томас

@BillyONeal - У чомусь ваш коментар був найкращою відповіддю. Ви можете мати всі переваги зберігання БД, але жодної проблеми.
B Сім

89

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

Однак! Деякі бази даних, як-от SQL Server, мають тип стовпця FILESTREAM. У цьому випадку ваші дані фактично зберігаються в окремому файлі на сервері баз даних, а в таблиці зберігається лише ідентифікатор файла. У цьому випадку я не бачу багато причин не зберігати дані на SQL сервері. Файли автоматично включаються як частина резервного копіювання сервера, а база даних та файли ніколи не синхронізуються. Проблема пропозиції Тоні щодо збереження імен файлів полягає в тому, що база даних та файлова система можуть вийти із синхронізації. База даних стверджує, що файл існує, коли він видалений на диску. Якщо процес модифікує базу даних, а потім виходить з ладу, файли та база даних не збігаються (тобто немає ACID з файлами поза базами даних).


21
Я не погоджуюся з твердженням: "Якщо процес модифікує БД, а потім виходить з ладу, файли та БД не збігаються". Якщо ви завершите весь процес в транзакції (створіть файл, підтвердіть файл, оновіть db) та викиньте повідомлення про помилки коли щось піде не так, то досить легко їх синхронізувати.
briddums

3
Я з бриддумами щодо цього: розглянути сценарій: зберігати файл у файловій системі (не видаляючи старий), оновити БД, успішно видалити старий файл, при відкаті видалити новий файл. Найгірший сценарій - якщо процес переривається, у вас є файл-сирота. Але у вас завжди є файли, на які посилається БД у правильній версії.
vartec

2
Інші потенційні проблеми з методом "Файл / БД": 1) Ви повинні робити оновлення в режимі копіювання під час запису. Якщо ваш процес виходить з ладу під час оновлення, стан БД буде скасовано назад, файл не буде. 2) Для цього потрібно певний збір сміття старого файлу. 3) Зберігання всього в БД означає, що версії БД і файлів синхронізуються після резервного копіювання. Відновіть БД до його стану 2 тижні тому ... тепер, де вміст файлів на той час?
Тімоті Болдрідж

3
@briddums - Ні, оскільки SQL Server інтегрується безпосередньо у файлову систему та керує цими файлами від імені ОС. Я сам їх не використовував, але документація робить це схожим на FILESTREAM і його потомковий файл FileTables надає вам найкраще з обох світів: Файли щільно пов'язані з базою даних та відповідними даними (дозволяючи централізовано керувати вашими даними) без здуття база даних.
Нік Чаммас

1
Я згоден з Ніком. Ми замінили нашу систему Disk + DB на стовпці FILESTREAM і жодного разу не озирнулися. Це дійсно приємно мати файли, прив’язані до інших таблиць за допомогою FK. Таким чином, ви можете сказати, що "кожна людина повинна мати один або кілька HR-документів, пов'язаних з ними", або щось подібне.
Тімоті Болдрідж

35

Так, це погана практика.

Вплив продуктивності на БД:

  • якщо ви працюєте SELECTз будь-яким стовпцем BLOB, ви завжди будете робити доступ до диска, тоді як без BLOB у вас є шанс отримати дані прямо з оперативної пам’яті (БД високої пропускної здатності буде оптимізовано для розміщення таблиць в оперативній пам’яті);
  • реплікація буде повільною, затримка реплікації великою, оскільки доведеться підштовхувати BLOB до рабів. Велика затримка реплікації спричинятиме всі види гоночних умов та інші проблеми синхронізації, якщо ви прямо не врахуєте це;
  • Резервне копіювання / відновлення БД займе набагато більше часу;

Перевага швидкості - немає ! Хоча деякі старі файлові системи не обробляють каталоги з мільйонами файлів, більшість сучасних взагалі не мають жодних проблем і фактично використовують такі ж структури даних, що і BD (як правило, B-дерева). Наприклад, ext4 (файлова система Linux за замовчуванням) використовує Htree .

Висновок: це буде перешкоджати роботі вашої БД і не покращить продуктивність пошуку файлів.

Крім того, оскільки ви говорите про веб-додаток - подання статичних файлів безпосередньо з файлової системи за допомогою сучасного веб-сервера, що дозволяє виконувати sendfile()системне виклик, - це величезне підвищення продуктивності. Звичайно, це неможливо, якщо ви отримуєте файли з БД. Розглянемо для прикладу цей орієнтир , показуючи, що Ngnix виконує 25 кк / с з 1000 одночасних з'єднань на ноутбуці низького рівня. Таке навантаження обсмажувало б будь-яку БД.


6
+1. Нехай ваш веб-сервер робить все, що найкраще, обслуговуючи файли з диска. Не змушуйте її запитувати PHP, оскільки PHP доведеться запитувати MySQL і т.д.
deizel

3
Коли програмісти дізнаються, що продуктивність - це не все, що має значення?
reinierpost

2
@reinierpost: lol. ймовірно, коли ми отримаємо спеціальність з гуманітарних мистецтв ;-)
vartec

1
@BillyONeal: чому ти вважаєш, що для статичного та динамічного контенту потрібно мати один сервер? Що стосується синхронізації файлів на серверах, існують спеціально розроблені для цього інструменти, набагато ефективніші, ніж бази даних. Використовувати базу даних як сервер файлів - це як намагатися забити цвях викруткою.
vartec

1
@BillyONeal: Я погоджуюся, що є деякі "рішення", де це буде працювати, я бачив досить багато аматорських налаштувань PHP із зображеннями в MySQL. Однак у таких налаштуваннях БД ніколи не підтримуватиме високий трафік, що обслуговує BLOB.
vartec

18

Я був би прагматичним щодо цього і дотримуюся принципу "ще не оптимізуй". Зробіть рішення, яке має сенс на даний момент, і рішення, яке маєте для розробки, щоб правильно реалізувати. Є багато потенційних проблем . Але це не обов'язково стає справжніми проблемами. Наприклад, це, мабуть, не буде проблемою, якщо у вас є 100 користувачів. Це може бути проблемою, якщо у вас є 100 000 або 10 000 000 користувачів. Але в останньому випадку повинна бути основа для збільшення ресурсів розвитку для вирішення всіх питань.

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

Я особисто вирішив би зберігати дані в базі даних, але переконайтесь, що BLOBS не читаються, поки вони справді не потрібні, тобто немає "SELECT * FROM ...", виконаного на тих таблицях, що містять блоги. І я би переконався, що дизайн спрощує переміщення даних із бази даних, у файлову систему, якщо у вас виникнуть проблеми з продуктивністю. Наприклад, збережіть інформацію про файл у окремій таблиці файлів , тим самим зберігаючи інформацію про файл подалі від інших суб’єктів господарювання.

Якщо припустити, що у вас є клас File для представлення файлу, прочитаного в базі даних, тоді вплив кодування згодом його переміщення буде мінімальним.


Це відмінна пропозиція. Не починайте вирішувати проблеми, яких у вас немає.
Важкий

16

Про це кілька років тому Microsoft випустила білий документ. Він зосереджений на SqlServer, але ви можете знайти там цікаву інформацію:

В BLOB чи ні в BLOB? Велике сховище об’єктів у базі даних чи файловій системі?

Дуже стислий варіант їх висновку:

Порівнюючи файлову систему NTFS і SQL Server 2005, BLOBS розміром менше 256 КБ ефективніше обробляє SQL Server, тоді як NTFS є більш ефективним для BLOBS більше 1 МБ.

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


4
Ви повинні знати, що NTFS починає вести себе дуже помилково, коли ви поміщаєте більше ніж 100 К файлів в один каталог. Доступ до файлів досить сповільнюється (принаймні на порядок), і операції з відкриття файлів починаються збиватися (мабуть) випадковим чином. Я відчував цей ефект у системах Windows 2008 та Windows 7. Коли я повторно розподіляв файли між кількома каталогами, все повернулося до нормального. Я не знаю, чи ситуація покращилася відтоді.
Ферруччо

11

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

Том Кіт, схоже, згоден :

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

Якщо він є в базі даних, я можу

будьте впевнені, що ним керується професійно

підкріплений

підлягає відновленню (з рештою даних)

забезпечений

масштабованість (спробуйте помістити 100000 документів у єдиний каталог, тепер покладіть їх у таблицю - яка з "масштабів" - це не каталог)

Я можу легко відмінити (flashback)

У мене є замок

Я читав послідовність ...


8

Так.

Якщо ви обслуговуєте файл з вашої файлової системи, ваш веб-сервер може використовувати код ядра, як sendfile () на BSD або Linux, щоб скопіювати файл безпосередньо в сокет. Це дуже швидко і дуже ефективно.

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

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


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

1
Я розумію, що питання щодо обслуговування файлів, завантажених користувачем. "Зараз я створюю веб-додаток, який дозволяє користувачам зберігати та обмінюватися файлами [...] Мені здається, що зберігання файлів у базі даних [...]". Я не думаю, що насправді так зручно робити звалища БД з великою кількістю мегабайтних крапок у базі даних. Також: так, важко мати справу з файлами; синхронізація, архівування - все складніше. Однак це не набагато складніше, і жертвувати продуктивністю в Інтернеті, щоб зберегти кілька рядків у своєму нічному сценарії резервного копіювання, є великою помилкою.
Еван П.

5

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

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

Однак, наприклад, з PostgreSQL, ви можете просто запустити інший екземпляр БД лише для зберігання блоків. Потім у вас є повна підтримка транзакцій. Але транзакційність коштує простору БД. Існує потреба в базі даних, щоб зберігати кілька екземплярів блобу для кількох одночасних транзакцій. Для PostgreSQL це найбільш болісно, ​​оскільки ця база даних зберігає дублікати крапок, зроблених для транзакцій, зберігаються, навіть якщо вони більше не потрібні, доки процес VACUUM не буде виконаний.

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

У системі, де файли додаються та видаляються, а транзакційний доступ до файлів не є проблемою, найкращим вибором буде зберігання файлової системи IMHO.


Привіт, коли ви сказали "використання ... Oracle для зберігання файлів просто неефективно", що робити, якщо ми вже використовуємо Oracle для зберігання інших нефайлових даних? Чи все-таки це буде неефективно?
Сяо Пен - ZenUML.com

RE: "Ви повинні бути дуже обережними, коли хтось модифікує файл" ... як колишній DBA Oracle, я повинен запропонувати зберігати великі файли поза базами даних і ніколи не дозволяти файлам змінюватись. Люди роблять помилки. Єдиний практичний спосіб управління відкатом (скасування) цих файлів - це впровадити для них систему Copy On Write. Таким чином, всі версії зберігаються та архівуються. Найдавніші можна перенести у віддалене сховище, обробляти публікацію для консолідації невеликих змін в одному архіві тощо
DocSalvager

5

Зазвичай найкраще зберігати великі BLOB в окремій таблиці та просто зберігати посилання іноземного ключа на BLOB у вашій головній таблиці. Таким чином, ви все одно можете отримати файл із бази даних (так що вам не потрібен спеціальний код) і уникнути проблем, пов’язаних із зовнішніми залежностями БД (підтримка синхронізації БД та файлової системи тощо), але ви лише зазнаєте цього накладних витрат якщо ви явно приєднаєтесь до цієї таблиці (або зробите окремий дзвінок). 10 Мб не дуже страшно, більшість сучасних комерційних баз даних не матимуть проблем. Єдина причина, за якою я зберігаю файл у файловій системі, - це скорочення пропускної здатності бази даних. Якщо у вашій базі даних буде перетасовано багато цих файлів, можливо, вам знадобиться розділити навантаження і зберегти лише дескриптор файлів якогось типу. Тоді ви можете мати окремий дзвінок, щоб завантажити файл з іншого сервера,


4

Ви можете зіткнутися з деякими з цих проблем:

  • Виконання завдання, SELECT *що стосується ряду з великою крапкою, займає дуже багато часу, навіть якщо вам не потрібна крапка (Звичайно, ви повинні зробити певний вибір, але іноді програми написані так)
  • Робити резервну копію може зайняти набагато більше часу. Залежно від ваших потреб вам може знадобитися заблокувати свої таблиці на час створення резервної копії, тому ви можете захотіти, щоб час резервного копіювання був низьким
  • Відновлення також займе набагато більше часу.
  • Якщо у вас не вистачає місця, вам доведеться придумати якийсь спосіб (можливо, переміщення всієї бази даних на новий сервер), щоб вирішити цю проблему. Зберігаючи файли у файловій системі, ви завжди можете встановити інший жорсткий диск і встановити м'які посилання.
  • Просто шукати файл для налагодження чи іншої інформації не так просто. Сюди також входять сценарії, які можуть не мати доступу до бази даних, але потребують деякої інформації з різних файлів.

Звичайно, ви також отримуєте деякі переваги:

  • Резервне копіювання даних та файлів у файлах вони синхронізовані
  • Видалення файла без знання бази даних неможливо
  • Вам не потрібно читати файл з диска, але це можна зробити в одному операторі sql
  • Ви можете завантажити базу даних, включити дамп у ваше середовище розробки та мати всі залежності саме там

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


1

Деякі системи управління вмістом Enterpirse, наприклад SiteCore, використовують одну базу даних для зберігання даних про сторінку та іншу базу даних для зберігання файлів. Вони використовують MS SQL Server.


як це відповідає на поставлене запитання?
гнат

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

1

Для практичного втілення ось, що вас може стосуватись:

Беніфіти:

  1. Весь вміст файлу безумовно синхронізований з вашою таблицею. Як зазначалося вище в коментарях, резервне копіювання даних є абсолютно зручним, оскільки вам не потрібно тримати синхронізовані дані з файловою системою.
  2. За допомогою кодування ви можете отримати вміст файлу безпосередньо з вибору SQL.
  3. З запиту ви навіть можете фільтрувати вміст файлу або його розмір явно з оператора SQL.

Недоліки:

  1. Порівняно з базою даних, структура якої семантично однакова, але не зберігає вміст файлів, база даних, як правило, споживає радикально більше пам’яті під час запитів.
  2. Автозавантаження може спричинити проблеми з продуктивністю, але не дуже. Давайте уявимо, що ваш сервер баз даних створює резервні копії речей кожні 6 годин, а в цих базах даних ви зберігаєте 10 Мб файл на запис. Цей сценарій - це не те, чого ви хочете.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.