1つのディレクトリにいくつのファイルを保存するかは重要ですか?もしそうなら、ディレクトリ内のファイルの数が多すぎるということです、そしてファイルが多すぎることの影響は何ですか? (これはLinuxサーバー上にあります。)
背景:私はフォトアルバムのWebサイトを持っています。アップロードされたすべての画像は8桁の16進数のIDに変更されます(たとえば、a58f375c.jpg)。これは、ファイル名の競合を避けるためです(たとえば、 "IMG0001.JPG"ファイルが多数アップロードされている場合など)。元のファイル名と有用なメタデータはデータベースに保存されます。今のところ、私はimagesディレクトリのどこかにおよそ1500のファイルがあります。これにより、ディレクトリ内のファイルの一覧表示に(FTPまたはSSHクライアントを介して)数秒かかるようになります。しかし、それ以外の効果があることはわかりません。特に、画像ファイルがユーザにどれだけ早く提供されるかには影響はありません。
0〜9とa〜fの16個のサブディレクトリを作成して、画像の数を減らすことを考えました。それから、ファイル名の最初の16進数が何であるかに基づいて、画像をサブディレクトリに移動します。しかし、FTP/SSH経由でディレクトリが時々一覧表示されることを除いて、そうする理由があるかどうかはわかりません。
1つのext3ディレクトリに800万を超えるファイルがあります。 libc readdir()
は、find
、ls
、およびこのスレッドで説明されている他の方法の大部分で、大きなディレクトリを一覧表示するために使用されます。
この場合ls
とfind
が遅いのは、readdir()
が一度に32Kのディレクトリエントリしか読み込めないためです。遅いディスクでは、ディレクトリを一覧表示するために多くの読み込みが必要になります。この速度の問題に対する解決策があります。私はそれについてかなり詳細な記事を書きました: http://www.olark.com/spw/2011/08/you-can-list-a-directory-with-8-million-files-but-not- with-ls/
重要なのは、getdents()
を直接使用することです - libc readdir()
に基づいたものではなく、http://www.kernel.org/doc/man-pages/online/pages/man2/getdents.2.html そのため、ディスクからディレクトリエントリを読み込むときにバッファサイズを指定できます。
それはLinuxサーバで使用されている特定のファイルシステムに少し依存します。現在のデフォルトは、dir_indexを指定したext3です。これにより、大きなディレクトリの検索が非常に速くなります。
だからあなたがすでに指摘したものを除いて、スピードは問題になるべきではありません。
1つのディレクトリ内のファイルの総数には制限があります。私はそれが間違いなく32000ファイルまで働いているのを覚えているようです。
私はそれに88,914のファイルがあるディレクトリを持っています。あなた自身のように、これはサムネイルを保存するためとLinuxサーバ上で使われます。
FTPまたはphp機能を介してリストされたファイルはそう遅いです、しかしファイルを表示することにパフォーマンスヒットもあります。例えばwww.website.com/thumbdir/gh3hg4h2b4h234b3h2.jpgの待機時間は200〜400ミリ秒です。他のサイトで比較したところ、ディレクトリ内に約100個のファイルがあり、画像は約40ms待った後に表示されます。
ほとんどの人がディレクトリ検索機能がどのように実行されるかを書いているので、私はこの答えを出しました。 。
Linuxでは、ファイルが多すぎるディレクトリがある場合、シェルはワイルドカードを拡張できないことがあります。私はLinuxでホストされているフォトアルバムでこの問題を抱えています。サイズ変更されたすべての画像を単一のディレクトリに格納します。ファイルシステムは多くのファイルを処理できますが、シェルは処理できません。例:
-Shell-3.00$ ls A*
-Shell: /bin/ls: Argument list too long
または
-Shell-3.00$ chmod 644 *jpg
-Shell: /bin/chmod: Argument list too long
私は今同様の問題に取り組んでいます。階層的なディレクトリ構造を持ち、ファイル名として画像IDを使用します。たとえば、id=1234567
の画像は次の場所に配置されます。
..../45/67/1234567_<...>.jpg
最後の4桁を使ってファイルの移動先を決めます。
数千の画像では、1レベルの階層を使用できます。私たちのシステム管理者は、効率性/バックアップ/その他の理由のために与えられたディレクトリ(ext3)に数千ファイルを提案しました。
それだけの価値があるので、ext4
ファイルシステム上に1,000,000個のファイルを含むディレクトリを作成し、次にWebサーバーを介してそれらのファイルにランダムにアクセスしました。私はそこにアクセスすることについて少しのプレミアムにも気付かなかった(例えば)そこに10ファイルしか持っていない。
これは 根本的に 数年前のntfs
でこれをやった経験とは異なります。
私が遭遇した最大の問題は32ビットシステムです。一定の数を超えると、「ls」などのツールは機能しなくなります。
その障壁を通過したら、そのディレクトリで何かをやろうとすることは大きな問題になります。
それは絶対にファイルシステムに依存します。最近のファイルシステムの多くはディレクトリの内容を格納するために適切なデータ構造を使用していますが、古いファイルシステムはエントリをリストに追加するだけなので、ファイルの取得はO(n)操作でした。
たとえファイルシステムが正しく動作しても、ディレクトリの内容をリストアップするプログラムがO(n ^ 2)ソートを実行することは絶対に可能です。安全のために、私は常に1ファイルあたりのファイル数を制限します。 500以下のディレクトリ。
それは本当に使用されるファイルシステム、そしてまたいくつかのフラグに依存します。
例えば、 ext3 は何千ものファイルを持つことができます。しかし、数千を経て、以前はとても遅くなっていました。ディレクトリを一覧表示するときだけでなく、単一のファイルを開くときにも。数年前、「htree」オプションが追加され、ファイル名を指定してiノードを取得するのに必要な時間が劇的に短縮されました。
個人的には、私はサブディレクトリを使用してほとんどのレベルを1000程度以下の項目に保っています。あなたの場合は、IDの最後の2桁の16進数で256個のディレクトリを作成します。最初の数字ではなく最後の数字を使用すると、負荷が分散されます。
ディレクトリ分割方式の実装にかかる時間が最小限であれば、私はそれを支持します。初めてコンソールを介して10000ファイルのディレクトリを操作することを含む問題をデバッグする必要があります。
一例として、F-Spotは写真ファイルをYYYY\MM\DD\filename.extとして保存します。これは、私の〜20000枚の写真コレクションを手動で操作するときに扱わなければならなかった最大のディレクトリが約800ファイルであることを意味します。これにより、ファイルをサードパーティ製アプリケーションからより簡単に参照できるようになります。あなたのソフトウェアがあなたのソフトウェアのファイルにアクセスする唯一のものであると思い込まないでください。
ext3には実際にディレクトリサイズの制限があり、それらはファイルシステムのブロックサイズに依存します。ディレクトリごとの「最大数」のファイルはありませんが、ディレクトリごとの「ファイルエントリの格納に使用される最大ブロック数」はありません。具体的には、ディレクトリ自体のサイズが高さ3のBツリーを超えて大きくなることはできず、ツリーのファンアウトはブロックサイズによって異なります。詳細についてはこのリンクを参照してください。
https://www.mail-archive.com/[email protected]/msg01944.html
私は最近2Kブロックでフォーマットされたファイルシステムに噛み付いた。それは私が別のext3ファイルシステムからコピーしていたときにディレクトリフルのカーネルメッセージwarning: ext3_dx_add_entry: Directory index full!
を不正確に受け取っていた。私の場合、たった48万ファイルのディレクトリはコピー先にコピーできませんでした。
問題は、ファイルをどうするかということです。
Windowsでは、2k以上のファイルを含むディレクトリはどれも私にとってはエクスプローラでゆっくり開く傾向があります。すべてが画像ファイルの場合、1kを超えるファイルはサムネイル表示で非常にゆっくり開く傾向があります。
かつては、システムによる制限は32,767でした。今はもっと高いですが、それでもそれはあまりにも多くのファイルを処理するには多すぎるのです。
出力に大量のファイルを作成していたプログラムを実行したことを思い出します。ファイルはディレクトリごとに30000でソートされています。生成された出力を再利用しなければならなかったときに、読み取りに問題があることを思い出しません。それは32ビットのUbuntu Linuxラップトップ上にあり、 Nautilus は数秒後にディレクトリの内容を表示していました。
ext3ファイルシステム:64ビットシステムでの同様のコードは、ディレクトリあたり64000ファイルをうまく処理しました。
私は同じ問題を抱えています。 ext4のUbuntuサーバーに何百万ものファイルを保存しようとしています。私自身のベンチマークを実行することになった。フラットディレクトリの方が使いやすく、パフォーマンスが優れていることがわかりました。
記事 を書きました。
私は同様の問題に遭遇しました。私は10,000以上のファイルがあるディレクトリにアクセスしようとしていました。ファイルリストを作成し、任意のファイルに対して任意の種類のコマンドを実行するのには時間がかかりすぎていました。
私は自分自身のためにこれを行うための小さなphpスクリプトを考え出し、それがブラウザでタイムアウトしないようにする方法を考え出すことを試みました。
以下は私が問題を解決するために書いたphpスクリプトです。
FTPにはファイルが多すぎるディレクトリ内のファイルのリスト表示
どのようにそれが誰かを助けます
私は @armandino と同じ方法を好みます。そのために、私はPHPの中でこの小さな関数を使ってIDをファイルパスに変換します。
function dynamic_path($int) {
// 1000 = 1000 files per dir
// 10000 = 10000 files per dir
// 2 = 100 dirs per dir
// 3 = 1000 dirs per dir
return implode('/', str_split(intval($int / 1000), 2)) . '/';
}
英数字を使いたい場合は、2番目のバージョンを使用することもできます。
function dynamic_path2($str) {
// 26 alpha + 10 num + 3 special chars (._-) = 39 combinations
// -1 = 39^2 = 1521 files per dir
// -2 = 39^3 = 59319 files per dir (if every combination exists)
$left = substr($str, 0, -1);
return implode('/', str_split($left ? $left : $str[0], 2)) . '/';
}
結果:
<?php
$files = explode(',', '1.jpg,12.jpg,123.jpg,999.jpg,1000.jpg,1234.jpg,1999.jpg,2000.jpg,12345.jpg,123456.jpg,1234567.jpg,12345678.jpg,123456789.jpg');
foreach ($files as $file) {
echo dynamic_path(basename($file, '.jpg')) . $file . PHP_EOL;
}
?>
1/1.jpg
1/12.jpg
1/123.jpg
1/999.jpg
1/1000.jpg
2/1234.jpg
2/1999.jpg
2/2000.jpg
13/12345.jpg
12/4/123456.jpg
12/35/1234567.jpg
12/34/6/12345678.jpg
12/34/57/123456789.jpg
<?php
$files = array_merge($files, explode(',', 'a.jpg,b.jpg,ab.jpg,abc.jpg,ddd.jpg,af_ff.jpg,abcd.jpg,akkk.jpg,bf.ff.jpg,abc-de.jpg,abcdef.jpg,abcdefg.jpg,abcdefgh.jpg,abcdefghi.jpg'));
foreach ($files as $file) {
echo dynamic_path2(basename($file, '.jpg')) . $file . PHP_EOL;
}
?>
1/1.jpg
1/12.jpg
12/123.jpg
99/999.jpg
10/0/1000.jpg
12/3/1234.jpg
19/9/1999.jpg
20/0/2000.jpg
12/34/12345.jpg
12/34/5/123456.jpg
12/34/56/1234567.jpg
12/34/56/7/12345678.jpg
12/34/56/78/123456789.jpg
a/a.jpg
b/b.jpg
a/ab.jpg
ab/abc.jpg
dd/ddd.jpg
af/_f/af_ff.jpg
ab/c/abcd.jpg
ak/k/akkk.jpg
bf/.f/bf.ff.jpg
ab/c-/d/abc-de.jpg
ab/cd/e/abcdef.jpg
ab/cd/ef/abcdefg.jpg
ab/cd/ef/g/abcdefgh.jpg
ab/cd/ef/gh/abcdefghi.jpg
$int
-バージョンでわかるように、すべてのフォルダには最大1000個のファイルがあり、最大99個のディレクトリに1000個のファイルと99個のディレクトリがあります。
しかし、多くのディレクトリに対してバックアッププロセスを短縮できることを忘れないでください。ディレクトリごとに1000から10000のファイルをテストしても構いませんが、ファイルごとにディレクトリファイルを読む場合はアクセス時間が非常に長くなるため(ftpクライアント、ファイル読み取り機能など)、これ以上追加しないでください。
最後に、ファイルの総数を減らす方法について考える必要があります。ターゲットに応じて、CSSスプライトを使用してアバター、アイコン、スマイリーなどの複数の小さな画像を結合することができます。 JSON形式で。私の場合、私は何千ものミニキャッシュを持っていたので、ついにそれらを10個のパックにまとめることにしました。
私はこれが完全にあなたが何が多すぎるかについてあなたの質問に答えるのではないことを尊重します、しかし長期的な問題を解決するためのアイデアはオリジナルのファイルメタデータを格納することに加えてそのメタデータを取り出します。フォルダがある程度の限界を超えて成長したら、パフォーマンス、美的な理由、またはなんらかの理由で快適なフォルダを作成したら、2番目のフォルダを作成してそこにファイルをドロップします。
上記の回答のほとんどが示していないのは、元の質問に対する「フリーサイズ」の回答がないことです。
今日の環境では、さまざまなハードウェアとソフトウェアの大規模な複合体があります。いくつかは32ビット、いくつかは64ビット、いくつかは最先端で、いくつかは試行錯誤されています。それに加えて、さまざまな新旧のハードウェア、新旧のOS、さまざまなベンダ(Windows、Unix、Appleなど)、そして無数のユーティリティとサーバーがあります。ハードウェアが改良され、ソフトウェアが64ビット互換性に変換されるにつれて、この非常に大きく複雑な世界のすべての部分を急速な変化の速度でうまく再生させるのに必然的にかなりの遅れがありました。
私見問題を解決する唯一の方法はありません。解決策は可能性を研究し、それから試行錯誤によってあなたの特定のニーズに最も適しているものを見つけることです。各ユーザーは、クッキーカッターアプローチを使用するのではなく、自分のシステムで何が機能するのかを判断する必要があります。
たとえば、メディアサーバーにいくつかの非常に大きなファイルがあります。結果は、3 TBドライブを埋める約400ファイルのみです。 iノードの1%のみが使用されていますが、全スペースの95%が使用されています。他の誰かが、たくさんの小さなファイルがあると、それらがスペースをいっぱいにする前にiノードを使い果たすかもしれません。理論的には、ディレクトリ内に含まれるファイルの総数はほぼ無限ですが、実用性は全体的な使用法が現実的な単位ではなく現実的な単位を決定することを決定します。ファイルシステムの機能だけです。
私は上記のすべての異なった答えが進歩への克服できない障壁を示すよりもむしろ思考と問題解決を促進したことを願っています。
OSの制限を超えない限り、「多すぎる」という数字はありません。ただし、OSに関係なく、ディレクトリ内のファイルが多いほど、個々のファイルへのアクセスにかかる時間が長くなり、ほとんどのOSではパフォーマンスが非線形になるため、10,000個のファイルから1つのファイルを見つけるには10倍以上かかります。それから1000のファイルを見つけるため。
ディレクトリ内に多数のファイルがあることに関連した二次的な問題には、ワイルドカード拡張の失敗が含まれます。リスクを軽減するために、アップロード日、またはその他の有用なメタデータの順にディレクトリを並べ替えることを検討してください。
答えではなく、いくつかの提案があります。
より適切なFS(ファイルシステム)を選択してください。歴史的な観点から、あなたの問題はすべて賢明なものであり、かつては何十年にもわたって発展してきたFSの中心的存在であった。私はもっと現代的なことを意味しますFSあなたの問題をよりよくサポートします。最初に、 FS list から最終目的に基づいて比較決定表を作成します。
私はあなたのパラダイムを変える時が来たと思います。だから私は個人的に 分散システムを意識したFS を使うことを勧めています。
私はうまくいくとは思いませんが、実験について触れていない場合は、現在のファイルシステムでAUFSを試してみてください。複数のフォルダを単一の仮想フォルダとして模倣する機能があると思います。
ハードウェアの制限を克服するために、RAID-0を使うことができます。