Я думаю о разработке моей собственной галереи на основе PHP для хранения большого количества изображений, может быть, десятков тысяч.
В базе данных я укажу на URL-адрес изображения, но вот проблема: я знаю, что нецелесообразно размещать все в одном каталоге на сервере, поскольку это замедлит доступ к сканированию, так как бы вы хранить их все? Какое-то дерево на основе имени jpeg / png?
Какие правила разделения изображений вы мне порекомендовали бы?
(Он будет ориентирован на использование в дешевых точечных coms, поэтому никакие манипуляции с сервером невозможны)


Используйте иерархию файловой системы. Идентифицируйте свои изображения, используя что-то вроде 001/002/003 / 004.jpg, было бы очень полезно. Однако разделение - это совсем другая история. Может быть случайным, на основе содержимого, на основе даты создания и т. д. На самом деле зависит от вашего приложения.
Вы можете ознакомиться со стратегией, используемой Apple iPod для хранения мультимедийного контента. Есть папки на одном уровне глубины и файлы с заголовками одинаковой ширины. Я считаю, что ребята из Apple потратили много времени на тестирование своего решения, поэтому оно может принести вам мгновенную пользу.
У нас была аналогичная проблема в прошлом. И нашел хорошее решение:
Мы убедились, что с помощью направляющих можно получить более или менее равномерное разделение. И это сработало как шарм.
Ссылки, которые могут помочь сгенерировать уникальный идентификатор:
Если вы все равно используете базу данных, почему бы просто не превратить ее в большой двоичный объект и позволить базе данных позаботиться об этом?
из-за производительности вызовы базы данных обычно очень дороги, особенно для двоичных данных, таких как изображения.
не говоря уже о том, что обслуживание изображений из базы данных означает, что вы почти всегда отправляете данные туда, где, как если бы вы могли обслуживать их из файловой системы, вы можете позволить браузеру / серверу обрабатывать кеширование изображений
@Gamecat IMHO, гораздо лучше, чем создание UUID, - это просто хешировать имя файла и использовать его начало в качестве имени каталога. Таким образом, вам не понадобится база данных, поскольку вы всегда можете пересчитать хэш, что намного быстрее, чем доступ к базе данных. (Я вижу, вы упомянули SHA-1, но не рекомендовали это явно).
@maaartinus, вы, наверное, правы. Но у нас уже была база данных (для CMS), которую нам просто нужно было связать с изображениями, и это отлично сработало для нас.
Понятно (я тоже буду использовать хэш и базу данных).
Если у вас есть целочисленный уникальный идентификатор, простой способ сделать это - разбить его на три уровня: xxx / yyy / filename.jpg. Таким образом, вы можете использовать уникальный идентификатор. Например, если идентификатор равен 100789, он будет сохранен как 100/789 / filename.jpg. Тогда у вас есть до 1000 каталогов на каждом уровне. И всего 1000000 файлов. И у вас может быть несколько имен файлов в зависимости от разрешения: thumbnail.jpg, small.jpg и т. д.
Я также рекомендую использовать в вашем хэше известную константу при создании имен папок. Это мешает загрузчикам легко определять папку, в которую вы помещаете свои файлы (они могут хэшировать свои собственные изображения с помощью sha1, если они знают, как вы создаете папки).
Если изображения, которые вы обрабатываете, являются цифровыми фотографиями, вы можете использовать данные EXIF для их сортировки, например, по дате съемки.
Вы можете хранить изображения в базе данных в виде больших двоичных объектов (varbinary для mssql). Таким образом, вам не нужно беспокоиться о хранилище или структуре каталогов. Единственным недостатком является то, что вы не можете легко просматривать файлы, но в любом случае это будет сложно в сбалансированном дереве каталогов.
ИМО, это плохой совет. 1. Вскоре ваша БД станет огромной, и это принесет другие проблемы. 2. С другой стороны, невозможно будет кэшировать изображения с помощью кэширующего прокси-сервера, такого как nginx или HAproxy, который очень быстро работает со статическим содержимым. 3. DB станет бутылочным горлышком при довольно низкой нагрузке.
Вы можете всегда иметь столбец DateTime в таблице, а затем хранить их в папках, названных по месяцам, годам или даже месяцам, дням и годам изображений, которые были добавлены в таблицу.
Пример
таким образом у вас останется не более трех папок.
Обычно я просто использую числовой идентификатор базы данных (auto_increment), а затем использую оператор модуля (%), чтобы выяснить, куда поместить файл. Просто и масштабируемо. Например, путь к изображению с идентификатором 12345 можно создать так:
12345 % 100 = 45
12345 % 1000 = 345
Заканчивается через:
/home/joe/images/345/45/12345.png
Или что-то типа того.
Если вы используете Linux, ext3 и файловую систему, вы должны знать, что существуют ограничения на количество каталогов и файлов, которые вы можете иметь в каталоге. Лимит для каталогов составляет 32000, поэтому вы всегда должны стремиться к тому, чтобы количество каталогов было низким.
Для чего нужны и «345», и «45»? Похоже, что в каждом из ваших каталогов первого уровня (например, «345») будет ровно один подкаталог (в данном случае «45»).
Несколько лет назад я работал над системой электронного документооборота, и мы сделали в значительной степени то, что предлагали Gamecat и wic.
То есть назначьте каждому изображению уникальный идентификатор и используйте его для получения относительного пути к файлу изображения. Мы использовали MOD, аналогичный тому, что предлагал wic, но мы разрешили 1024 папки / файла на каждом уровне, с 3 уровнями, поэтому мы могли поддерживать файлы размером 1 ГБ.
Однако мы удалили расширение из файлов. Записи БД содержали MIME-тип, поэтому расширение не требовалось.
Я бы не рекомендовал хранить полный URL-адрес в записи БД, только ID изображения. Если вы сохраняете URL-адрес, вы не можете переместить или реструктурировать свое хранилище без преобразования вашей БД. Относительный URL-адрес будет приемлемым, поскольку таким образом вы можете, по крайней мере, перемещать репозиторий изображений, но вы получите больше гибкости, если просто сохраните идентификатор и получите URL-адрес.
Кроме того, я бы не рекомендовал разрешать прямые ссылки на ваши файлы изображений из Интернета. Вместо этого предоставьте URL-адрес серверной программы (например, Java Servlet) с идентификатором изображения, указанным в URL-запросе (http://url.com/GetImage?imageID=1234).
Сервлет может использовать этот идентификатор для поиска записи БД, определения типа MIME, определения фактического местоположения, проверки ограничений безопасности, ведения журнала и т. д.
хорошие моменты. позволяет ли запрос сервлета кэшировать? Я наблюдаю аналогичную проблему, но в моем приложении время передачи имеет решающее значение, поэтому я искал способы кэширования изображений на клиенте. Я сплю?
@MikeJ: Вы можете создать отдельный класс для доступа к изображениям. Этот класс будет знать, как получить путь из идентификатора и т. д. Он также может содержать кеш, возможно, как хеш-таблицу, которой вы управляете самостоятельно, или, возможно, консервированный класс кеша. Сервлет будет получать изображения с этого объекта, а не с диска.
Посмотрите на файловую систему XFS. Он поддерживает неограниченное количество файлов, и Linux поддерживает это. http://oss.sgi.com/projects/xfs/papers/xfs_usenix/index.html
При сохранении файлов, связанных с идентификаторами auto_increment, я использую что-то вроде следующего, которое создает три уровня каталогов, каждый из которых состоит из 1000 каталогов и 100 файлов в каждом каталоге третьего уровня. Это поддерживает ~ 100 миллиардов файлов.
если $ id = 99532455444, то следующее возвращает / 995/324/554/44
function getFileDirectory($id) {
$level1 = ($id / 100000000) % 100000000;
$level2 = (($id - $level1 * 100000000) / 100000) % 100000;
$level3 = (($id - ($level1 * 100000000) - ($level2 * 100000)) / 100) % 1000;
$file = $id - (($level1 * 100000000) + ($level2 * 100000) + ($level3 * 100));
return '/' . sprintf("%03d", $level1)
. '/' . sprintf("%03d", $level2)
. '/' . sprintf("%03d", $level3)
. '/' . $file;
}
I know is impractical to have all of them sitting at the same directory in the server as it would slow access to a crawl.
Это предположение.
Я разработал системы, в которых миллионы файлов хранились в одном каталоге, и это прекрасно работало. Это также самая простая в программировании система. Большинство файловых систем сервера поддерживают это без проблем (хотя вам нужно будет проверить, какую из них вы используете).
http://www.databasesandlife.com/flat-directories/
Спасибо, что поделился. OP упомянул PHP, и одна практическая проблема заключается в том, что доступ по FTP к каталогу с большим количеством файлов может истекать.
Я думаю, важно сказать, как вы это делаете в своей статье в блоге, что файловые системы некоторый поддерживают очень большое количество файлов в одной папке. По моему опыту, некоторые (другие) файловые системы работают за пределами заявленных спецификаций для больших # файлов, но не все файловые операции будут работать. Если вы собираетесь хранить очень большое количество файлов в одной папке, сначала проверьте это! Тем не менее, почему бы просто не сбалансировать структуру папок в виде дерева с помощью какого-либо хеша?
В настоящее время я столкнулся с этой проблемой, и то, что написал Исаак, заинтересовало меня этой идеей. Моя функция немного отличается.
function _getFilePath($id) {
$id = sprintf("%06d", $id);
$level = array();
for($lvl = 3; $lvl >= 1; $lvl--)
$level[$lvl] = substr($id, (($lvl*2)-2), 2);
return implode('/', array_reverse($level)).'.jpg';
}
Мои изображения исчисляются тысячами, поэтому у меня есть только этот предел до 999999, поэтому он разделится на 99/99 / 99.jpg или 43524 на 04/35 / 24.jpg
Я не очень понимаю, что вы здесь имеете в виду. Вы можете привести пример?