Хранение большого количества изображений - PullRequest
48 голосов
/ 15 января 2009

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

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

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

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

Ответы [ 12 ]

46 голосов
/ 15 января 2009

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

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

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

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

11 голосов
/ 15 января 2009

Я работал над системой электронного документооборота несколько лет назад, и мы сделали в значительной степени то, что предложили Gamecat и wic.

То есть присвойте каждому изображению уникальный идентификатор и используйте его для определения относительного пути к файлу изображения. Мы использовали MOD, подобный тому, что предлагал wic, но мы разрешили 1024 папки / файла на каждом уровне, с 3 уровнями, чтобы мы могли поддерживать файлы 1G.

Однако мы удалили расширение из файлов. Записи БД содержали тип MIME, поэтому расширение не требовалось.

Я бы не рекомендовал хранить полный URL-адрес в записи БД, только ID изображения. Если вы храните URL-адрес, вы не можете переместить или реструктурировать свое хранилище без преобразования вашей БД. Относительный URL-адрес будет в порядке, так как таким образом вы можете по крайней мере перемещать хранилище изображений, но вы получите большую гибкость, если просто сохраните идентификатор и получите URL-адрес.

Кроме того, я бы не рекомендовал разрешать прямые ссылки на ваши файлы изображений из Интернета. Вместо этого предоставьте URL-адрес для программы на стороне сервера (например, сервлет Java) с идентификатором изображения, который указывается в запросе URL-адреса (http://url.com/GetImage?imageID=1234).

Сервлет может использовать этот идентификатор для поиска записи в БД, определения типа MIME, определения фактического местоположения, проверки ограничений безопасности, ведения журнала и т. Д.

8 голосов
/ 15 января 2009

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

12345 % 100 = 45
12345 % 1000 = 345

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

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

Или что-то в этом роде.

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

7 голосов
/ 18 августа 2010

Я знаю, что нецелесообразно размещать их все в одном каталоге на сервере, поскольку это замедлит доступ к сканированию.

Это предположение.

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

http://www.databasesandlife.com/flat-directories/

5 голосов
/ 28 июля 2010

При сохранении файлов, связанных с идентификаторами 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;
}
2 голосов
/ 10 декабря 2009

Посмотрите на файловую систему XFS. Он поддерживает неограниченное количество файлов, и Linux поддерживает его. http://oss.sgi.com/projects/xfs/papers/xfs_usenix/index.html

1 голос
/ 05 марта 2011

Я сейчас сталкиваюсь с этой проблемой, и то, что написал Исаак, заинтересовало меня этой идеей. Хотя моя функция немного отличается.

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

1 голос
/ 15 января 2009

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

Пример

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

таким образом, вы получите не более 3 папок.

0 голосов
/ 15 января 2009

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

0 голосов
/ 15 января 2009

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

...