Хранение большого количества изображений

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

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

Какие правила разделения изображений вы мне порекомендовали бы?

(Он будет ориентирован на использование в дешевых точечных coms, поэтому никакие манипуляции с сервером невозможны)

Применение градиента к изображению с помощью CSS
Применение градиента к изображению с помощью CSS
Здравствуйте, братья и сестры, как дела? Недавно я застрял на применении градиента к изображению. Я применял это много раз, но иногда наши требования...
Получение URL-адреса изображения курса в Moodle с помощью PHP
Получение URL-адреса изображения курса в Moodle с помощью PHP
Moodle - это популярная система управления обучением с открытым исходным кодом, используемая многими учебными заведениями и организациями по всему...
51
0
13 250
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Используйте иерархию файловой системы. Идентифицируйте свои изображения, используя что-то вроде 001/002/003 / 004.jpg, было бы очень полезно. Однако разделение - это совсем другая история. Может быть случайным, на основе содержимого, на основе даты создания и т. д. На самом деле зависит от вашего приложения.

Вы можете ознакомиться со стратегией, используемой Apple iPod для хранения мультимедийного контента. Есть папки на одном уровне глубины и файлы с заголовками одинаковой ширины. Я считаю, что ребята из Apple потратили много времени на тестирование своего решения, поэтому оно может принести вам мгновенную пользу.

Я не очень понимаю, что вы здесь имеете в виду. Вы можете привести пример?

Rik Heywood 15.01.2009 14:14
Ответ принят как подходящий

У нас была аналогичная проблема в прошлом. И нашел хорошее решение:

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

Мы убедились, что с помощью направляющих можно получить более или менее равномерное разделение. И это сработало как шарм.

Ссылки, которые могут помочь сгенерировать уникальный идентификатор:

Если вы все равно используете базу данных, почему бы просто не превратить ее в большой двоичный объект и позволить базе данных позаботиться об этом?

falstro 15.01.2009 14:26

из-за производительности вызовы базы данных обычно очень дороги, особенно для двоичных данных, таких как изображения.

Mike Geise 15.01.2009 14:32

не говоря уже о том, что обслуживание изображений из базы данных означает, что вы почти всегда отправляете данные туда, где, как если бы вы могли обслуживать их из файловой системы, вы можете позволить браузеру / серверу обрабатывать кеширование изображений

MikeJ 24.03.2009 15:31

@Gamecat IMHO, гораздо лучше, чем создание UUID, - это просто хешировать имя файла и использовать его начало в качестве имени каталога. Таким образом, вам не понадобится база данных, поскольку вы всегда можете пересчитать хэш, что намного быстрее, чем доступ к базе данных. (Я вижу, вы упомянули SHA-1, но не рекомендовали это явно).

maaartinus 21.03.2011 21:04

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

Toon Krijthe 21.03.2011 22:56

Понятно (я тоже буду использовать хэш и базу данных).

maaartinus 22.03.2011 02:07

Если у вас есть целочисленный уникальный идентификатор, простой способ сделать это - разбить его на три уровня: xxx / yyy / filename.jpg. Таким образом, вы можете использовать уникальный идентификатор. Например, если идентификатор равен 100789, он будет сохранен как 100/789 / filename.jpg. Тогда у вас есть до 1000 каталогов на каждом уровне. И всего 1000000 файлов. И у вас может быть несколько имен файлов в зависимости от разрешения: thumbnail.jpg, small.jpg и т. д.

B Seven 03.05.2011 11:27

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

Steve Midgley 10.11.2014 21:33

Если изображения, которые вы обрабатываете, являются цифровыми фотографиями, вы можете использовать данные EXIF ​​для их сортировки, например, по дате съемки.

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

ИМО, это плохой совет. 1. Вскоре ваша БД станет огромной, и это принесет другие проблемы. 2. С другой стороны, невозможно будет кэшировать изображения с помощью кэширующего прокси-сервера, такого как nginx или HAproxy, который очень быстро работает со статическим содержимым. 3. DB станет бутылочным горлышком при довольно низкой нагрузке.

Roman Podlinov 30.04.2013 19:41

Вы можете всегда иметь столбец DateTime в таблице, а затем хранить их в папках, названных по месяцам, годам или даже месяцам, дням и годам изображений, которые были добавлены в таблицу.

Пример

  1. 2009 г.
  2. -01
  3. --01
  4. --02
  5. --03
  6. --31

таким образом у вас останется не более трех папок.

Обычно я просто использую числовой идентификатор базы данных (auto_increment), а затем использую оператор модуля (%), чтобы выяснить, куда поместить файл. Просто и масштабируемо. Например, путь к изображению с идентификатором 12345 можно создать так:

12345 % 100 = 45
12345 % 1000 = 345

Заканчивается через:

/home/joe/images/345/45/12345.png

Или что-то типа того.

Если вы используете Linux, ext3 и файловую систему, вы должны знать, что существуют ограничения на количество каталогов и файлов, которые вы можете иметь в каталоге. Лимит для каталогов составляет 32000, поэтому вы всегда должны стремиться к тому, чтобы количество каталогов было низким.

Для чего нужны и «345», и «45»? Похоже, что в каждом из ваших каталогов первого уровня (например, «345») будет ровно один подкаталог (в данном случае «45»).

Dustin Boswell 05.11.2010 11:36

Несколько лет назад я работал над системой электронного документооборота, и мы сделали в значительной степени то, что предлагали 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 24.03.2009 15:35

@MikeJ: Вы можете создать отдельный класс для доступа к изображениям. Этот класс будет знать, как получить путь из идентификатора и т. д. Он также может содержать кеш, возможно, как хеш-таблицу, которой вы управляете самостоятельно, или, возможно, консервированный класс кеша. Сервлет будет получать изображения с этого объекта, а не с диска.

Clayton 24.03.2009 20:05

Посмотрите на файловую систему 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 к каталогу с большим количеством файлов может истекать.

James P. 06.05.2011 00:14

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

Steve Midgley 10.11.2014 21:36

В настоящее время я столкнулся с этой проблемой, и то, что написал Исаак, заинтересовало меня этой идеей. Моя функция немного отличается.

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

Другие вопросы по теме