LINUX.ORG.RU

Картинки в БД

 , , ,


1

1

Хранение картинок в БД: как это делать и стоит ли?
База данных: MySQL. Физически в ней можно хранить изображения? Какие при этом ограничения? В каком виде хранятся картинки в базе данных? А если base64 перевести?
А может не надо? Может, лучше ссылки хранить? А у пользователя такие картинки кэшироваться будут? База данных разжиреет, дампы тяжёлые будут, или нет?
А может я всё неправильно делаю? Может мне вообще это не надо? Может, мне нужно другую БД юзать?
Если кратко, поясните мне поясните мне по хардкору все методы работы, плюсы, минусы и подводные камни.

★★★★★

стоит ли?

ни в коем случае

Может, лучше ссылки хранить?

да

JFreeM ★★★☆
()

мне нужно другую БД юзать?

угу, файлуха это и есть самая подходящая БД для файлов

true_admin ★★★★★
()

Тут народ намекает на GridFS. Надо будет пощупать, идея интересная :)

KRoN73 ★★★★★
()

Вообще, GridFS в Mongo - довольно неплохо справляется я раздачей файлов. Но, если не заморачиваться - храни имена файлов в базе, сами файлы - в ФС.

helios ★★★★★
()

хранить можно (blob), но не стоит. не для того оно предназначено. лучше храни бинарные файлы (картинки) в обычной файловой системе, а чтобы директория с кучей файлов не разжирела - разбивай на поддиректории, и самое простое - это по дате "./storage/2012/08/19/snap1337.jpg". можно еще по md5 хэшу разбивать на поддиректории, но я бы не стал (зачем лишняя нагрузка, получить дату дешевле).

статику кэширует клиент (браузер), лишь спрашивая сервер «изменилось ли оно».
позволь объясню. кэш, о которым ты спрашиваешь, реализуется на клиентсткой стороне (но его можно выключить, я всегда выключаю в браузере его, хе-хе), и когда браузер запрашивает какой-то документ - как всегда, сервер может ему ответить либо 200 OK и отдать документ, либо 304 Not modified (документ не изменился) и закрыть соединение, и документ браузер выдаст тебе из своего кэша. нагрузки при этом на твой сервер никакой, кроме того как распарсить и выполнить запрос.
на серверной же стороне для таких случаев применяют дополнительные заголовки типа Last-modified, Etag и другие, и суют их в php скрипты, чтобы так же php скриптом при запросе сразу ответить, что страница не изменилась и закрыть соединение, а php скрипт не дальше выполнять - это тоже выходит дешево.
а еще у nginx есть встроенный fastcgi_store, который кэширует результат выполнения скриптов по запрашиваемому URI, и при повторном запросе, если кэш не устарел, отдаст его, и это тоже очень и очень дешево (в итоге, городить свои костыли в php (или где-то еще) с кэшированием больше без надобности).
а я делаю иным образом. на сайте используются ЧПУ, бэкенд (скрипт) их парсит, выполняет и сохраняет результат в статичный .html файл соблюдая иеархию ЧПУ, который уже отдает сервер при повторных запросах не трогая бэкенд (php) вообще. можно хоть на github pages зеркалировать такой статичный сайт. мне кажется это лучшим вариантом. ну, что может быть дешевле, чем отдать .html статику? остается ее только грамотно хранить (разбивать на поддиректории, когда сайт станет огромным)
и... что-то меня не туда понесло.

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

Spoofing ★★★★★
()

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

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

ты собираешься хранить картинки в mysql? а чем ты их оттуда доставать будешь? насколько мне известно, nginx не умеет отдавать статику прямо из mysql (он, кстати, умеет это делать из memcached). php скриптом? а теперь представь, через какой огород все это пройдет, прежде чем клиент получит свою картинку? nginx (распарсит запрос клиента, запустит fastcgi скрипт), php (подключится к mysql, выполнит запрос) mysql (достанет картинку и отдаст ее php, а потом все в обратном порядке) против того, что nginx выполнит запрос чтобы сразу отдать картинку из памяти (которую отдаст ядро).

кстати, о memcached. я на эту тему проводил бенчмарк и даже он оказался медленее, чем если бы nginx просто отдавал картинку с винта (просто запомни, что с винта оно отдается лишь один раз, а потом кэшируется в памяти ядром, и уже отдается из памяти - очень, очень, очень быстро)
у nginx еще есть кэш для статики, open_file_cache называется.

так вот, бенчмарк. 100000 запросов с 50 клиентов.
nginx из memcached отдавал статичный html 46 секунд, и memcached нехило так сжирал процессорное время (память, само собой).
nginx с open_file_cache (который умеет из коробки, HttpCoreModule) отдавал с винта тот-же статичный html 20 секунд.

итог. тебе нужно просто отдавать статику клиенту? забудь про mysql, забудь про memcached. самое дешевое - это самое простое, когда ты все отдаешь сразу с винта (в дальнейшем из памяти). НЕ ПЛОДИ СУЩНОСТИ!!1111

моя статья на тему кэширования и очень полезно почитать комменатрии: http://habrahabr.ru/post/147247/

будь здоров :)

Spoofing ★★★★★
()
Ответ на: комментарий от Spoofing

но я бы не стал (зачем лишняя нагрузка, получить дату дешевле)

Тогда получится огромная гора папок с одним-двумя файлами. Хэши ещё увеличивают баланс между количеством папок и количеством фалов в них.

Kalashnikov ★★★
()
Ответ на: комментарий от Kalashnikov

Согласен. Тогда с датой даже еще лучше балансировать, - время идет и не кончится никогда, можно убрать дни, а складывать в директории «месяцы» (или «недели»), или даже «годы» если файлов совсем чуть-чуть за год скапливается. ./storage/2012/picture.jpg, ./storage/2012/July/picture.jpg - в зависимости от нагрузки.
365 поддиректорий в год не так много, но разумеется, только они они оправдывают себя и в каждой хранится 2к+ картинок. Иначе лучше хранить в неделях. Иначе лучше хранить в месяцах. Иначе в годах. Иначе в веках. :)

В случае md5 хэшей все еще есть вероятность большого количества коллизий (когда у кучи картинок будут, например, первые две буквы хэша одинаковыми) и ресурс остается исчерпаем. Спасибо что подметили это.

Spoofing ★★★★★
()
Ответ на: комментарий от GateKeeper

Если проект таких масштабов, то в блобах тем более не стоит хранить (да и велосипедить в общем-то тоже не стоит). Ну и никто не мешает подобрать фс и размер блока/количество инодов специально под задачу.

Kalashnikov ★★★
()
Ответ на: комментарий от GateKeeper

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

Это уже иного рода ресурс от его исчерпаемости никакой способ хранения не спасет, и может я ошибаюсь.. но городить огород из кучи приложений я не считаю выходом. Нужно смотреть по ситуации, какого рода это картинки (может семейные фотографии размером 5мб каждая, и тогда затраченные ресурсы оправдают себя). Главное - KISS!

Spoofing ★★★★★
()
Ответ на: комментарий от Spoofing

никто не мешает подобрать фс и размер блока/количество инодов специально под задачу

вот!

Spoofing ★★★★★
()
Ответ на: комментарий от Spoofing

то тогда как вариант - склеивать кучу файлов вместе, а в какой-нибудь базе хранить идентификатор файла (имя), оффсет (позицию, откуда он начинается) и его размер

Я сам не знаю «правильного» ответа на этот вопрос, но в твоем ответе мне кажется, что никаким KISS уже не пахнет - как и откуда доставать информацию о том, изменился ли файл? Во-вторых, придется костылить плагин для веб-сервера, чтобы умел считывать эти самые блоки (мы же не приложением хотим отдавать статику?). Склейка весьма подходит для iconset store. Там да, если ты хочешь вот эту вот иконочку, наверное, ты всё равно захочешь все остальные, чтобы не выбиваться из общего стилевого оформления, остальное сделает css и жабаскрипт. Но даже там склеивают не путем for FILE in $dir; do cat $FILE >> dirname($dir)/glued.dat; done а тем же PIL/ImageMagick/GD.

GateKeeper ★★
()
Ответ на: комментарий от GateKeeper

Следующий комментарий - есть правильный ответ :) До него, сам не знал что лучше.

Spoofing ★★★★★
()
Ответ на: комментарий от GateKeeper

никто не мешает подобрать фс и размер блока/количество инодов специально под задачу

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

это явно проще и лучше всего вышеперечисленного)..

Spoofing ★★★★★
()
Ответ на: комментарий от GateKeeper

Я погуглил. tune2fs -l /dev/sda3 | grep resize_inode должен быть.

mkfs.ext4 -N <number-of-inodes>
Overrides the default calculation of the number of inodes that should be reserved for the filesystem (which is based on the number of blocks and the bytes-per-inode ratio). This allows the user to specify the number of desired inodes directly.

Но это только во время создания фс, так что, как было уже сказано. нужно изначально решать все под конкретную задачу)..

Spoofing ★★★★★
()
Ответ на: комментарий от GateKeeper

man tune2fs мне сказал, что менять inode count нельзя.

А в reiserfs они выделяются динамически и поэтому их количество не имеет значения. Кроме того, рейзер заметно лучше себя ведёт при больших количествах файлов.

AnDoR ★★★★★
()
Ответ на: комментарий от AnDoR

Сравни скорость отдачи 1кк файлов и возвращайся.

сравнил отключением питания, отдача там была 7 млн. Что еще нужно сделать?

xpahos ★★★★★
()
Ответ на: комментарий от xpahos

Мы тут 22ТБ-раздел на XFS решили проверить и запустили xfs_check. Оно ругнулось, что out of memory, и подохло. Гугл говорит, что багу больше 5 (а то и 7) лет. Тоже дохлая.

GateKeeper ★★
()
Ответ на: комментарий от xpahos

Это вопрос, как было, или вопрос, пробовали ли? Хотя, в любом случае - поздно. Там уже недоZFS.

GateKeeper ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.