分割できないファイルがある場合は、より大きなブロック サイズを使用することをお勧めします。つまり、ファイル自体と同じ大きさ (またはそれより大きくても違いはありません)。
ブロック サイズが全体のファイル サイズよりも小さい場合、すべてのブロックが同じデータ ノード上にない可能性があり、データの局所性が失われます。ブロックごとにマップ タスクが作成されるため、これは分割可能なファイルでは問題になりません。
ブロック サイズの上限については、特定の古いバージョンの Hadoop では制限が 2GB であったことを知っています (これを超えるとブロックの内容を取得できませんでした) - https://issues.apache.org/jira/browse/HDFS-を参照してください。 96
小さいファイルを大きなブロック サイズで保存することのマイナス面はありません。この点を強調するために、それぞれブロック サイズが 2 GB の 1 MB と 2 GB のファイルを考えてみましょう。
- 1 MB - 1 ブロック、ネーム ノードの単一エントリ、各データ ノード レプリカに物理的に格納される 1 MB
- 2 GB - 1 ブロック、名前ノードの単一エントリ、各データ ノード レプリカに物理的に格納された 2 GB
そのため、必要な物理ストレージを除けば、名前ノード ブロック テーブルにマイナス面はありません (両方のファイルがブロック テーブルに 1 つのエントリを持っています)。
考えられる唯一の欠点は、小さいブロックと大きいブロックを複製するのにかかる時間ですが、反対に、データ ノードがクラスターから失われた場合、2000 x 1 MB ブロックを複製するタスクは、単一のブロック 2 GB ブロックよりも遅くなります。 .
更新 - 実際の例
これが混乱を引き起こしているのを見て、いくつかの実際の例を以下に示します。
HDFS ブロック サイズが 300 MB のシステムがあり、簡単にするために、データ ノードが 1 つだけの疑似クラスターがあるとします。
1100 MB のファイルを保存する場合、HDFS はそのファイルを最大300 MB のブロックに分割し、データ ノードの特別なブロック インデックス ファイルに保存します。データ ノードに移動して、インデックス付きブロック ファイルが物理ディスク上のどこに格納されているかを確認すると、次のように表示される場合があります。
/local/path/to/datanode/storage/0/blk_000000000000001 300 MB
/local/path/to/datanode/storage/0/blk_000000000000002 300 MB
/local/path/to/datanode/storage/0/blk_000000000000003 300 MB
/local/path/to/datanode/storage/0/blk_000000000000004 200 MB
ファイルは 300 MB で正確に割り切れないため、ファイルの最終ブロックは、ブロック サイズによるファイルのモジュロとしてサイズ設定されることに注意してください。
ここで、ブロック サイズよりも小さいファイル (たとえば 1 MB) で同じ演習を繰り返し、それがデータ ノードにどのように格納されるかを見てみましょう。
/local/path/to/datanode/storage/0/blk_000000000000005 1 MB
繰り返しになりますが、データ ノードに格納されている実際のファイルは 1 MB であり、299 MB のゼロ パディングを含む 200 MB のファイルではありません(これが混乱の原因だと思います)。
ブロックサイズが効率の要因となる場所は、名前ノードにあります。上記の 2 つの例では、名前ノードはファイル名のマップを維持し、ブロック名とデータ ノードの場所 (および合計ファイル サイズとブロック サイズ) を保持する必要があります。
filename index datanode
-------------------------------------------
fileA.txt blk_01 datanode1
fileA.txt blk_02 datanode1
fileA.txt blk_03 datanode1
fileA.txt blk_04 datanode1
-------------------------------------------
fileB.txt blk_05 datanode1
fileA.txt に 1 MB のブロック サイズを使用する場合、上記のマップでは 4 ではなく 1100 のエントリが必要になることがわかります (名前ノードでより多くのメモリが必要になります)。また、すべてのブロックをプルバックすると、datanode1 に対して 4 回ではなく 1100 回の RPC 呼び出しを行うことになるため、コストが高くなります。