クロスプラットフォームの大きなコンテナ ファイルを作成するための代替手段はありますか?

StackOverflow https://stackoverflow.com/questions/257832

質問

以前、私が質問したのは、 質問.

問題は、ファイル構造の要求が非常に高いことです。

たとえば、最大 4500 個のファイルと 500MB のデータを含むコンテナーを作成しようとしています。

このコンテナのファイル構造は次のようになります。

  • SQLite DB (1MB未満)
  • テキストベースの XML のようなファイル
  • 残りの 4,500 個ほどのファイルを構成する動的フォルダー構造内の画像

  • 最初の作成後、画像ファイルは削除を除き読み取り専用になります。

  • 小さなデータベースは、コンテナーにアクセスするときに定期的に使用されます。

Tar、Zip などは (圧縮率が 0 であっても) 遅すぎます。遅いというのは主観的なものですが、このサイズのコンテナを解凍するには 20 秒以上かかります。

何かご意見は?

役に立ちましたか?

解決

三つのこと。

1) ティモシー・ウォルターズが言ったことは正しいので、さらに詳しく説明します。

2) 4500 ファイルと 500Mb のデータは、単純に大量のデータとディスク書き込みです。データセット全体を操作している場合、速度が遅くなります。まさにI/Oの真実。

3) 他の人が述べたように、ユースケースの詳細はありません。

読み取り専用のランダム アクセスのシナリオを想定すると、Timothy の言うことはほぼ当てはまり、実装は簡単です。

簡単に言うと、やることは次のとおりです。

すべてのファイルを 1 つの BLOB に連結します。それらを連結している間、ファイル名、ファイルの長さ、および BLOB 内でファイルが開始されるオフセットを追跡します。その情報を名前順に並べ替えてデータ ブロックに書き込みます。これを目次、または目次ブロックと呼びます。

次に、2 つのファイルを連結します。単純なケースでは、最初に TOC ブロックがあり、次にデータ ブロックがあります。

この形式からデータを取得する場合は、TOC でファイル名を検索し、データ ブロックの先頭からのオフセットを取得し、TOC ブロック サイズを追加して、FILE_LENGTH バイトのデータを読み取ります。単純。

賢明にしたい場合は、BLOB ファイルの最後に TOC を置くことができます。次に、TOC の先頭へのオフセットを最後に追加します。次に、ファイルの最後までシークし、(数値のサイズに応じて) 4 バイトまたは 8 バイトをバックアップし、その値を取得して、さらに目次の先頭までシークします。そうすれば振り出しに戻ります。これを行うと、最初にアーカイブを 2 回再構築する必要がなくなります。

目次をブロック (たとえば、サイズが 1K バイト) にレイアウトすると、目次に対して二分検索を簡単に実行できます。各ブロックにファイル情報エントリを入力するだけです。スペースがなくなったら、マーカーを書いてゼロを埋めて、次のブロックに進みます。バイナリ検索を行うには、TOC のサイズがすでにわかっているので、途中から開始して最初のファイル名を読み取り、そこから開始します。すぐにブロックが見つかり、ブロックを読み取ってファイルをスキャンします。これにより、目次全体を RAM に保存しなくても、効率的に読み取ることができます。もう 1 つの利点は、ブロッキングに必要なディスク アクティビティが、TAR のようなチェーン スキーム (何かを見つけるためにアーカイブをクロールする必要がある) よりも少ないことです。

ファイルをブロック サイズに合わせてパディングすることをお勧めします。ディスクは通常のサイズのデータ​​ ブロックを扱うのと同様、これも難しくありません。

全体を再構築せずにこれを更新するのは困難です。更新可能なコンテナ システムが必要な場合は、より単純なファイル システム設計を検討することをお勧めします。その場合、それが本当に探しているものだからです。

移植性に関しては、ほとんどの標準ライブラリにはこれらの詳細を処理するルーチンがあるため、2 進数をネットワーク順序で保存することをお勧めします。

他のヒント

コンテナで任意のファイルシステム操作(コンテナ内の新しいファイルの作成、削除、既存のファイルの上書き、追加など)を実行しているように見えるため、何らかのファイルシステムを使用する必要があると思います。大きなファイルを割り当て、その中にファイルシステム構造を作成します。

利用可能なファイルシステムにはいくつかのオプションがあります。BerkeleyUFSとLinux ext2 / ext3の両方で、利用可能なユーザーモードライブラリがあります。 FATの実装がどこかにある可能性もあります。ファイルシステムの構造を理解し、拡張できるものを選択してください-ext2は(別のブロックグループによって)拡張するのがかなり簡単で、FATは拡張するのが難しい(FATに追加する必要がある)ことを知っています。

別の方法として、ファイルシステムの下に仮想ディスク形式を配置して、ブロックの任意の再マッピングを許可することもできます。その後、「無料」ファイルシステムのブロックはディスク上に表示される必要がなく、仮想コンテナを実際のコンテナファイルよりもはるかに大きく割り当てることができます。

ファイルへの読み取り専用アクセスのみが必要になるという仮定に基づいて作業するのは、なぜそれらをすべて一緒にマージし、2番目の「インデックス」を持っているのですか?ファイル(またはヘッダー内のインデックス)は、ファイル名、開始位置、および長さを示します。必要なことは、開始点にシークし、正しいバイト数を読み取ることだけです。方法は言語によって異なりますが、ほとんどの言語で非常に簡単です。

最も難しい部分は、データファイルとインデックスの作成になります。それでも基本的なことです!

ISOディスクイメージがトリックを行う可能性があります。多数のファイルを簡単に保持でき、すべての主要なオペレーティングシステム上の多くのソフトウェアでサポートされている必要があります。

最初に、質問を拡大してくれてありがとう、より良い答えを提供するのに大いに役立ちます。

とにかくSQLiteデータベースが必要になることを考えると、すべてをデータベースに入れるパフォーマンスを検討しましたか?私の経験はSQL Server 2000/2005/2008に基づいているので、SQLiteの機能については肯定的ではありませんが、削除を許可しながら、レコードを検索してデータを取得するための非常に高速なオプションになると確信していますおよび/または更新オプション。

通常、データベース内にファイルを配置することはお勧めしませんが、すべての画像の合計サイズが4500枚の画像で約500MBであることを考えると、1枚の画像につき100Kを少し超えていますか?動的パスを使用して画像を保存している場合は、少し正規化されたデータベースに「ImagePaths」を作成できます。各パスをIDにマップするテーブル、そのPathIDの画像を検索し、必要に応じてBLOB列からデータをロードできます。

XMLファイルはSQLiteデータベースにも存在する可能性があります。これにより、問題なくWindowsとOSXの間を移動できるアプリの単一の「データファイル」が得られます。必要なパフォーマンスと互換性を提供するには、単にSQLiteエンジンに依存するだけです。

最適化の方法は使用方法によって異なります。たとえば、特定のパスですべての画像を頻繁に取得する必要がある場合は、PathID(パフォーマンスのための整数)を使用すると高速になりますが、すべてを表示する場合「A」で始まる画像プロパティとしてパスを表示するだけで、ImageName列のインデックスがより有用になります。

これは時期尚早の最適化のように聞こえますが、「十分に高速」に動作するソリューションを見つける必要があり、そのメカニズムを抽象化してアプリケーション(またはMacとPCの両方がある場合は両方のアプリ)バージョン)シンプルなリポジトリなどを使用すると、アプリケーションに影響を与えることなく、ストレージ/検索方法を自由に変更できます。

ソリッドファイルシステムを確認します-必要なもののようです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top