Comments 41
0. Хранить файлы в БД концептуально не верно.
На мой взгляд, аргумент должен быть только один. База данных создана для хранения и поиска структурированных данных, и хороша (быстра) именно тогда, когда ее используют по прямому назначению. В других случаях она быстро становится узким местом. Что делать? Использовать специально созданный «инструмент» для хранения файлов — файловую систему. Со своей задачей она обычно справляется весьма достойно. Уж по крайней мере более достойно, чем MySQL.
P. S. А вообще в настоящее время наблюдается такая активность вокруг NoSQL-баз, что даже удивительно видеть, что кому-то до сих пор приходят в голову идеи, за которые еще 10 лет назад по рукам били.
P. S. А вообще в настоящее время наблюдается такая активность вокруг NoSQL-баз, что даже удивительно видеть, что кому-то до сих пор приходят в голову идеи, за которые еще 10 лет назад по рукам били.
В общем случае нельзя.
НО всё всегда зависит от уровня задачи и от уровня разработчика.
Даже денормализация(чистое зло) в некоторых случаях полезна.
НО всё всегда зависит от уровня задачи и от уровня разработчика.
Даже денормализация(чистое зло) в некоторых случаях полезна.
В принципе можно, кто ж запретит :)
Просто будет медленно и геморройно. Тут надо помнить, что для того, чтобы аватарка попала в браузер к юзеру, браузер делает отдельный http-реквест. Если аватара лежит на диске, апач (или кто там у Вас) отдаст ее сам, и об этом не придется думать вообще (причем вполне возможно, что часто используемые файлы будут уже закешированы в оперативе на уровне операционки, и диск не будет тревожиться). Если аватара лежит в базе, нужно как минимум сделать запрос и отдать файлик юзеру самостоятельно. Если это мелкая картинка — хрен с ней. Если же это что-то большее, то Вам придется тратить драгоценную оперативку чтобы это что-то поместилось в памяти. А если нужна докачка, еще и городить очередной велосипед. Даже для менее тривиального случая, когда, например, нужно проверить права доступа к картинке, есть относительно простые решения. Например, под мод-перлом можно навесить авторизационный хендлер на директорию с файлами. В нем перед отдачей Вы проверяете юзерские права доступа и возвращаете в апача код (пускать или не пускать). А с отдачей файлов он разберется самостоятельно.
Просто будет медленно и геморройно. Тут надо помнить, что для того, чтобы аватарка попала в браузер к юзеру, браузер делает отдельный http-реквест. Если аватара лежит на диске, апач (или кто там у Вас) отдаст ее сам, и об этом не придется думать вообще (причем вполне возможно, что часто используемые файлы будут уже закешированы в оперативе на уровне операционки, и диск не будет тревожиться). Если аватара лежит в базе, нужно как минимум сделать запрос и отдать файлик юзеру самостоятельно. Если это мелкая картинка — хрен с ней. Если же это что-то большее, то Вам придется тратить драгоценную оперативку чтобы это что-то поместилось в памяти. А если нужна докачка, еще и городить очередной велосипед. Даже для менее тривиального случая, когда, например, нужно проверить права доступа к картинке, есть относительно простые решения. Например, под мод-перлом можно навесить авторизационный хендлер на директорию с файлами. В нем перед отдачей Вы проверяете юзерские права доступа и возвращаете в апача код (пускать или не пускать). А с отдачей файлов он разберется самостоятельно.
При использовании nginx можно применять X-ACCEL-REDIRECT — хэдер посылается апачем к nginx и разрешает тому выдать статический файл (любой). Получается самый выгодный вариант, мы проверяем права доступа к статике с помощью апача, базы данных и движка, на котором работает сайт, а собственно отдает статику уже nginx.
Интересная тема. Я тоже долго сомневался, взвешивал все за и против. Но решил хранить файлы таким образом: все загруженные пользователем файлы храню в блобах. Но показываю файлы из кэша. Т.к. нужно несколько «представлений» файла изображения (превью, с измененными цветовой гаммой, и т.д.) после каждого из этих преобразований результат записывается в файловую систему, и ему выставляется TTL. Таким образом, если этот файл был кому нибудь возвращен и его TTL не закончилось, то вернется версия из кэша(файловой системы). Если нет, выгрузим из БД и положим в кэш, вернем пользователю.
Интересно ваше мнение.
Интересно ваше мнение.
А что конкретно дает Вам хранение тела файла в блобе?
интересно почему всё таки решили в БЛОБах а не на диске, тем более обрабатывать было бы легче?
Обработка ведь абсолютно не причем, какая разница откуда массив байт из БД или из файловой системы?
Почему блобы — пункты 3,4,5.
Почему блобы — пункты 3,4,5.
3. Из файловой системы получать быстрее (правда кешированием управлять вручную скорее всего не удастся), опять же при переносе сайта вы же не только базу данных копируете, но и файлы сайта, т.е. файлы-то тоже копируете, потому тут я не вижу никаких плюсов для БД в этом пункте.
Не спорю что быстрее. В моем случае придется подождать только первый раз. Второй запрос будет из файловой системы.
Нет, файлы мне зачем? Все автоматически закэшируется.
Нет, файлы мне зачем? Все автоматически закэшируется.
«В моем случае придется подождать только первый раз. Второй запрос будет из файловой системы.»
ну а в случае с ФС, вам не нужно будет ждать в первый раз и запрос будет из ней же =)
«Нет, файлы мне зачем? Все автоматически закэшируется.»
Т.е. вы от сайта скачаете только БД и она будет работать, как у вас тот же сайт будет работать? =) (поверю только в случае всяких MongoDB и CouchDB, но о них отдельный разговор)
ну а в случае с ФС, вам не нужно будет ждать в первый раз и запрос будет из ней же =)
«Нет, файлы мне зачем? Все автоматически закэшируется.»
Т.е. вы от сайта скачаете только БД и она будет работать, как у вас тот же сайт будет работать? =) (поверю только в случае всяких MongoDB и CouchDB, но о них отдельный разговор)
Вот смотрите, камень преткновения хранения файлов в БД это скорость и архитектурные «проблемы». Я их решил с помощью такого «фасада». И получил гибкость в управлении этими файлами.
Извините, второй вопрос не понял. Все же просто.
Извините, второй вопрос не понял. Все же просто.
зависит от нагрузки на сайт и количества данных. 100 гигов наберёте — никакой фасад не поможет.
аргументы? если данные закэшированны (т.е. их представления уже лежат на диске) почему я буду проигрывать при нагрузке?
база 100 гигов не влезает в память, каждый запрос в базу шуршит винтом, производительность базы в целом резко падает даже при одном хите в секунду в базу за картинкой.
думаю такой сценарий самый вероятный.
думаю такой сценарий самый вероятный.
Вы описываете сценарий без кэша на винте. Вся нужная информация уже закэширована и в запросах в БД нет необходимости.
то есть фотографии не добавляются и кэш не экспайрится?
или у вас вообще один хит за картинкой при 100 гигов картинок? это что же за сервис такой?
или у вас вообще один хит за картинкой при 100 гигов картинок? это что же за сервис такой?
Если в запросах нет необходимости, значит Вам тем более не нужно хранить файл в базе по причинам, которые указал Вам товарищ строчкой выше. Судя по комментариям, Вы пока не очень четко представляете, в какие проблемы может вылиться на крупном проекте такое отношение к БД.
Какие проблемы???? Какое отношение к БД???
Ок, начнем с начала. У нас есть таблица с блобом (фалом пользователя). Есть сервлет, которы по запросу (допусти это первый запрос) достане блоб из бд, проведет нужные преобразования, запишет результат на диск. Так же, в кэше появится запись что эта операция уже проводилась и ее результат лежит на диске. В следующий раз когда придет запрос на этот файл с теми же преобразованиями, вернется уже обработаный ранее результат (тот который на диске). Если этот файл стал никому не интересен и он долго ни кем не запрашивался, он удаляется из диска и из кэша. Остается только эталон в БД.
Чем такая схема плоха? Пожалуйста объясните, я видимо чего то не понимаю.
Ок, начнем с начала. У нас есть таблица с блобом (фалом пользователя). Есть сервлет, которы по запросу (допусти это первый запрос) достане блоб из бд, проведет нужные преобразования, запишет результат на диск. Так же, в кэше появится запись что эта операция уже проводилась и ее результат лежит на диске. В следующий раз когда придет запрос на этот файл с теми же преобразованиями, вернется уже обработаный ранее результат (тот который на диске). Если этот файл стал никому не интересен и он долго ни кем не запрашивался, он удаляется из диска и из кэша. Остается только эталон в БД.
Чем такая схема плоха? Пожалуйста объясните, я видимо чего то не понимаю.
После прочтения этой ветки комментариев я так и не смог понять для чего вы сделали такую схему?
Если все дело в легкости переноса системы между хостингами/серверами, то спросите себя а так ли часто вы этим занимаетесь и компенсирует ли время, сэкономленное на переносе время затраченное на написание этой системы и время на обработку незакешированных файлов?
Если все дело в легкости переноса системы между хостингами/серверами, то спросите себя а так ли часто вы этим занимаетесь и компенсирует ли время, сэкономленное на переносе время затраченное на написание этой системы и время на обработку незакешированных файлов?
0) если проверку и отдачу кеша осуществляет скрипт, а не стандартные средства вебсервера, вы уже сильно теряете производительность
1) здесь человек справедливо предположил, что кеш рано или поздно имеет свойство протухать. Какой процент попаданий в непротухший кеш у вас будет при, скажем, миллионе пользователей умеренной активности и TTL, не уходящем в бесконечность?
2) здесь и еще где-то написано про кеш базы, который Вы успешно выключаете такими таблицами
3) здесь написано про проблемы администрирования вашей таблички с аттачами
4) здесь написано про проблемы с масштабированием жирных баз, которые Вы явно не догнали.
По пункту 4 отдельно. Если Вы не знаете о стандартных паттернах, которыми люди решают проблему производительности базы (а значит и о самих проблемах, которые приходится так решать), может перестанете упорствовать, пока не разберетесь что к чему? Ваш метод работает, никто ведь не спорит. Но работает на небольших проектах. Как только Вы получите приличную нагрузку, проект ляжет именно здесь, и Вы ЗАДОЛБАЕТЕСЬ это исправлять, когда данных будет много, а проект будет лежать. Я больше не хочу Вас в этом убеждать, если не верите — проведите эксперимент. Забейте в базу побольше записей; замерьте скорость отдачи с учетом того, что кеш будет тухнуть и в базу таки придется лазить; выверьте кол-во запросов, которые одновременно выдерживает Ваш сайт; помедитируйте над цифрами… :)
1) здесь человек справедливо предположил, что кеш рано или поздно имеет свойство протухать. Какой процент попаданий в непротухший кеш у вас будет при, скажем, миллионе пользователей умеренной активности и TTL, не уходящем в бесконечность?
2) здесь и еще где-то написано про кеш базы, который Вы успешно выключаете такими таблицами
3) здесь написано про проблемы администрирования вашей таблички с аттачами
4) здесь написано про проблемы с масштабированием жирных баз, которые Вы явно не догнали.
По пункту 4 отдельно. Если Вы не знаете о стандартных паттернах, которыми люди решают проблему производительности базы (а значит и о самих проблемах, которые приходится так решать), может перестанете упорствовать, пока не разберетесь что к чему? Ваш метод работает, никто ведь не спорит. Но работает на небольших проектах. Как только Вы получите приличную нагрузку, проект ляжет именно здесь, и Вы ЗАДОЛБАЕТЕСЬ это исправлять, когда данных будет много, а проект будет лежать. Я больше не хочу Вас в этом убеждать, если не верите — проведите эксперимент. Забейте в базу побольше записей; замерьте скорость отдачи с учетом того, что кеш будет тухнуть и в базу таки придется лазить; выверьте кол-во запросов, которые одновременно выдерживает Ваш сайт; помедитируйте над цифрами… :)
Нет что Вы, я не упорствую. Просто хочется услышать конструктивную критику, а не простое «все у вас упадет».
0) на выходе будет стоять HTTP сервер который и будет заниматься реальной отдачей файлов (так что здесь производительность я не теряю)
1) Какой процент хитов на новости прошлого года? На мой взгляд это не страшно.
2) не понял про что Вы
3) согласен
4) видимо и сейчас не догоняю.
Я знаком с паттернами поэтому не очень переживаю что нужно будет много переделывать (всего лишь подменить два лоадера)
Мне интересно почему Вы так боитесь за «протухший» кэш? Вы же можете оценить вероятность хита по «протухшей» записи? Согласитесь она не велика.
Обязательно, проведу краш тест, но не сейчас. Это не так важно на данный момент.
В общем конструировать этот велосипед я начал из-за того что мне не нравится разносить источники данных. + люблю хот деплой модули которые сами знают что им делать и мне приходится меньше работать ) Не исключаю что в этом случае я ошибаюсь, время покажет.
Как бы то ни было было интересно почитать комментарии.
0) на выходе будет стоять HTTP сервер который и будет заниматься реальной отдачей файлов (так что здесь производительность я не теряю)
1) Какой процент хитов на новости прошлого года? На мой взгляд это не страшно.
2) не понял про что Вы
3) согласен
4) видимо и сейчас не догоняю.
Я знаком с паттернами поэтому не очень переживаю что нужно будет много переделывать (всего лишь подменить два лоадера)
Мне интересно почему Вы так боитесь за «протухший» кэш? Вы же можете оценить вероятность хита по «протухшей» записи? Согласитесь она не велика.
Обязательно, проведу краш тест, но не сейчас. Это не так важно на данный момент.
В общем конструировать этот велосипед я начал из-за того что мне не нравится разносить источники данных. + люблю хот деплой модули которые сами знают что им делать и мне приходится меньше работать ) Не исключаю что в этом случае я ошибаюсь, время покажет.
Как бы то ни было было интересно почитать комментарии.
Про 3 Вам уже написали. Про 4 — в бд можно хранить метаинформацию, которую Вы будете проверять при доступе, но отдать файл эффективнее родного механизма apache или nginx из своего скрипта Вы не сможете (там этот механизм вылизан так, что ни один нормальный человек не будет этот гемор повторять в своей софтине). Про 5 вообще непонятно. Сейчас идет тенденция отказа от централизации в пользу децентрализованных систем, которые проще масштабировать.
Впрочем, ладно. Если Вам хватает производительности, пользуйтесь так.
Кстати из личного опыта. Очень трудно и долго было перетряхивать 100гиговую мускуль-базу, которая загружена 24х7, чтобы вынести хранящиеся в табличках аттачменты в файловую систему. Кто-то из авторов CRM Request Tracker в свое время остроумно подумал, что так будет удобнее.
Впрочем, ладно. Если Вам хватает производительности, пользуйтесь так.
Кстати из личного опыта. Очень трудно и долго было перетряхивать 100гиговую мускуль-базу, которая загружена 24х7, чтобы вынести хранящиеся в табличках аттачменты в файловую систему. Кто-то из авторов CRM Request Tracker в свое время остроумно подумал, что так будет удобнее.
Про 4, согласен, такой вариант у меня в запасе если что-то пойдет не так.
Про 5 мне непонятно что вам не понятно. При чем тут децентрализованные системы? БД разве не выступает в нашем случае «децентрализованной системой»? Что может быть проще расширяться имея БД и тучу серверов? Может я вас не правильно понял.
Аттачменты из таблиц будут выноситься только по надобности и удаляться по истечению TTL.
Про 5 мне непонятно что вам не понятно. При чем тут децентрализованные системы? БД разве не выступает в нашем случае «децентрализованной системой»? Что может быть проще расширяться имея БД и тучу серверов? Может я вас не правильно понял.
Аттачменты из таблиц будут выноситься только по надобности и удаляться по истечению TTL.
БД децентрализуется хуже чем хотелось бы. Плодить слейвы можно, но остается узкое место с мастер-базой (да, ее можно сделать мастер-мастер, но не до бесконечности). Разбивать базу на шарды? Тоже выход, но далеко не всегда простой в реализации. На фоне всех этих проблем снятие с базы нагрузки по отдаче файлов выглядит простым, дешевым и эффективным решением, которое сразу уберет бОльшую часть проблем.
зачем столько писать если хватило бы — нет.
4. пункт тоже не аргумент
доступ вы можете разграничивать например по URL (как и было задумано): site.name.ru/files/BUCH/bla-bla-file
или по путю к файлу, это уже дело конечной реализации и в плане БД это не намного удобнее.
Из файловой системы опять же файл можно получать поточно (т.е. прогресс например отображать загрузки если файл большой). Опять же в БД большие файлы хранить тяжелее, т.е. их надо дробить и писать код который их собирает.
5. Про централизованное хранение тоже считаю что сказано общно как-то, у вас же проекты только из БД не состоят. И в БД и при помощи файловых систем и различных протоколов доступа файлы можно хранить как централизованно, так и децентрализованно. Поэтому это никакой не плюс, а просто неинформированность.
доступ вы можете разграничивать например по URL (как и было задумано): site.name.ru/files/BUCH/bla-bla-file
или по путю к файлу, это уже дело конечной реализации и в плане БД это не намного удобнее.
Из файловой системы опять же файл можно получать поточно (т.е. прогресс например отображать загрузки если файл большой). Опять же в БД большие файлы хранить тяжелее, т.е. их надо дробить и писать код который их собирает.
5. Про централизованное хранение тоже считаю что сказано общно как-то, у вас же проекты только из БД не состоят. И в БД и при помощи файловых систем и различных протоколов доступа файлы можно хранить как централизованно, так и децентрализованно. Поэтому это никакой не плюс, а просто неинформированность.
Я предлагаю не мелочиться и хранить файлы БД MySQL на реляционной файловой системе.
О, интересная тема! Про хранение файлов была моя первая статья на Хабре (http://habrahabr.ru/blogs/mysql/45966/) тогда тоже нашлось много как сторонников так и противников хранения файлов в БД
Но многие так и не поняли ключевую идею — файлы должны храниться именно в виде файлов, не блобов или чего еще. Просто файлов в файловой системе, тогда вебсервер будет макс быстро отдавать из не напрягая БД. А вот управлять файлами может БД. Тоесть следить за уникальностью имен, удалением файлов при удалении записи и т.д.
Там же в комментах подсказали, что скажем в MS SQL Server реализованы Filestream для такой работы с файлами, в MySQL эе про такие я пока не слышал.
Но многие так и не поняли ключевую идею — файлы должны храниться именно в виде файлов, не блобов или чего еще. Просто файлов в файловой системе, тогда вебсервер будет макс быстро отдавать из не напрягая БД. А вот управлять файлами может БД. Тоесть следить за уникальностью имен, удалением файлов при удалении записи и т.д.
Там же в комментах подсказали, что скажем в MS SQL Server реализованы Filestream для такой работы с файлами, в MySQL эе про такие я пока не слышал.
Кстати, есть подозрение, что жЫрные блобы будут оседать в кеше мускуля на общих основаниях (и забивать его). Эксперты, я прав или там уже подстелена соломка?
Мне кажется, лучше всего делать ссылку на файл в БД, сам файл хранить на диске. Тогда получается, легко сделать пункт 4, да и вся система выигрывает.
Лучше всего если фаилов много, хранить их на S3. Если душит жаба можно городить локальный кэш. Будет дешево, сердито и надежно.
А из-за товарищей которые любят аттачи сохранять в БД получается, что для тривиального проекта БД разрастается до нескольких сотен гигов. А дальше вылезает куча проблем, с тем, что уже банальный alter на таблицу с фаилами сделает ее лок на полдня.
А из-за товарищей которые любят аттачи сохранять в БД получается, что для тривиального проекта БД разрастается до нескольких сотен гигов. А дальше вылезает куча проблем, с тем, что уже банальный alter на таблицу с фаилами сделает ее лок на полдня.
Нет, нет и нет и причем без комментариев.
Никаких файлов в БД
Споры начинают, студенты 1-х курсов гостиничного хозяйства.
Никаких файлов в БД
Споры начинают, студенты 1-х курсов гостиничного хозяйства.
Sign up to leave a comment.
Стоит ли хранить файлы в БД MySQL?