web-dev-qa-db-ja.com

多数の画像を保存する

たくさんの写真、おそらく数万枚を保存するための独自のPHPベースのギャラリーを開発することを考えています。

データベースで画像のURLを指定しますが、ここに問題があります。クロールへのアクセスが遅くなるため、サーバー内の同じディレクトリにすべてを配置するのは実用的ではないことがわかっています。それらすべてを保存しますか? jpeg/pngの名前に基づいたある種の木?

画像を分割するためのどのようなルールをお勧めしますか?

(これは安価なドットコムでの使用に焦点を合わせているため、サーバーとのマングリングは不可能です)

48
Saiyine

過去にも同様の問題がありました。そして、素晴らしい解決策を見つけました:

  • 各画像に一意のGUIDを与えます。
  • サブイメージ(サムネイル、縮小サイズなど)の名前、場所、GUID、および可能な場所を含む各イメージのデータベースレコードを作成します。
  • GUIDの最初(1つまたは2つ)の文字を使用して、最上位フォルダーを決定します。
  • フォルダのファイルが多すぎる場合は、もう一度分割してください。参照を更新すると、準備が整います。
  • ファイルの数とアクセス数が多すぎる場合は、フォルダーをさまざまなファイルサーバーに分散させることができます。

ギッドを使用すると、ほぼ均一な分割が得られることを経験しました。そしてそれは魅力のように機能しました。

一意のIDの生成に役立つ可能性のあるリンク:

46
Toon Krijthe

私は数年前に電子文書管理システムに取り組み、Gamecatとwicが提案したことをほぼ実行しました。

つまり、各画像に一意のIDを割り当て、それを使用して画像ファイルへの相対パスを導出します。 wicが提案したのと同様のMODを使用しましたが、1Gファイルをサポートできるように、各レベルで1024個のフォルダー/ファイルを3つのレベルで許可しました。

ただし、ファイルから拡張子を削除しました。 DBレコードにはMIMEタイプが含まれていたため、拡張子は必要ありませんでした。

完全なURLをDBレコードに保存することはお勧めしません。画像IDのみを保存します。 URLを保存する場合、DBを変換せずにストレージを移動または再構築することはできません。相対URLは、少なくとも画像リポジトリを移動できるので問題ありませんが、IDを保存してURLを取得するだけで、柔軟性が高まります。

また、Webから画像ファイルへの直接参照を許可することはお勧めしません。代わりに、サーバー側プログラム(Javaサーブレット)など)へのURLを指定し、URLクエリ(http://url.com/GetImage?imageID=1234)。

サーブレットは、そのIDを使用して、DBレコードの検索、MIMEタイプの判別、実際の場所の取得、セキュリティ制限の確認、ロギングなどを行うことができます。

11
Clayton

私は通常、数値データベースID(auto_increment)を使用してから、モジュラス(%)演算子を使用してファイルを配置する場所を特定します。シンプルでスケーラブル。たとえば、ID12345の画像へのパスは次のように作成できます。

12345 % 100 = 45
12345 % 1000 = 345

最終的に:

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

またはそのようなもの。

Linuxとext3およびファイルシステムを使用している場合は、ディレクトリとディレクトリに含めることができるファイルの数に制限があることに注意する必要があります。制限はdirsの32000であるため、dirsの数を低く保つように常に努力する必要があります。

8
Martin Wickman

クロールへのアクセスが遅くなるため、それらすべてをサーバー内の同じディレクトリに配置することは実用的ではないことを私は知っています。

これは仮定です。

私は何百万ものファイルを1つのディレクトリにフラットに保存するシステムを設計しましたが、それはうまく機能しました。また、プログラミングが最も簡単なシステムです。ほとんどのサーバーファイルシステムは問題なくこれをサポートしています(ただし、使用しているものを確認する必要があります)。

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

7
Adrian Smith

Auto_increment IDに関連付けられたファイルを保存するときは、次のようなものを使用します。これにより、それぞれ1000個のディレクトリで構成される3つのディレクトリレベルと、各第3レベルのディレクトリに100個のファイルが作成されます。これは約1,000億のファイルをサポートします。

$ 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;
}
5
Isaac

XFSファイルシステムを見てください。それは無制限の数のファイルをサポートし、Linuxはそれをサポートします。 http://oss.sgi.com/projects/xfs/papers/xfs_usenix/index.html

2
EXTROMEDIA

私は現在この問題に直面しており、Isaacが書いたことで私はそのアイデアに興味を持ちました。 Tho私の関数は少し異なります。

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';
}

私の画像は数千にすぎないので、これは99999までの制限しかなく、99/99 /99.jpgまたは43524に04/35/24.jpgに分割されます

1
Mikhail

テーブルにDateTime列があり、テーブルに追加された画像の月、年、さらには月、日、年にちなんで名付けられたフォルダにそれらを保存することができます。

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

このようにして、3つ以下のフォルダの深さになります。

1
Mike Geise

ファイルシステムの階層を使用します。 001/002/003 /004.jpgのようなものを使用して画像にIDを付けると非常に役立ちます。ただし、パーティショニングは別の話です。ランダム、コンテンツベース、作成日ベースなどがあります。実際には、アプリケーションが何であるかによって異なります。

0
PolyThinker

Apple iPodのマルチメディアコンテンツを保存するために使用されている戦略を確認してください。1つのレベルの深さのフォルダと同じ幅のタイトルのファイルがあります。Appleみんながソリューションのテストに多くの時間を費やしたので、すぐにメリットが得られるかもしれません。

0
Boris Pavlović

扱っている写真がデジタル写真の場合、EXIFデータを使用して、たとえばキャプチャ日で並べ替えることができます。

0
Keltia

画像をblobとしてデータベースに保存できます( varbinary for mssql)。そうすれば、ストレージやディレクトリ構造について心配する必要はありません。唯一の欠点は、ファイルを簡単に参照できないことですが、バランスの取れたディレクトリツリーではそれは難しいでしょう。

0