8

10 億個のファイルを含む外部ディスクがあります。外部ディスクをコンピューター A にマウントすると、プログラムはすべてのファイルのパスをスキャンし、ファイルのパスをデータベース テーブルに保存します。その後、外部ディスクを取り出すと、それらのデータはテーブルに残ります。問題は、コンピューター B で一部のファイルが削除され、それをコンピューター A に再度マウントした場合、コンピューター A のデータベース テーブルを同期する必要があることです。多くの時間を浪費し、多くのメモリを浪費します。使用するメモリを最小限に抑えながら、すべてのファイルをスキャンせずにデータベース テーブルを更新する方法はありますか?

その上、私の場合、メモリの制限は時間よりも重要です。つまり、時間を節約するよりもメモリを節約したいということです。

ファイルを多くのセクションに分割し、特定の関数 (SHA1 など) を使用して、このセクションのファイルが削除されているかどうかを確認できると思います。ただし、ファイルをセクションに分割する方法がわかりません。誰かが私を助けたり、より良いアイデアを教えてくれますか?

4

4 に答える 4

1

ディスク上のファイル システムを制御できない場合は、ディスク全体のファイル名をスキャンするしかありません。削除されたファイルを一覧表示するには、次のようにします。

update files in database: set "seen on this scan" to false
for each file on disk do:
    insert/update database, setting "seen on this scan" to true
done
deleted files = select from files where "seen on this scan" = false

データベースのパフォーマンスの問題に対する解決策は、ファイル名をある種のリストに蓄積し、たとえば 1000 ファイルに達するたびに一括挿入/更新を行うことです。

10 億個のファイルを含むディレクトリについては、ファイルを一覧表示するコードを、C 関数opendirreaddir. 私だったら、今のところあまり気にしないでしょう。正気な人が 1 つのディレクトリに 10 億個のファイルを持っているとは限りません。そのようなことは、ファイル システムや一般的な OS ツールを無効にするため、リスクは低く、解決策は簡単です。

于 2012-05-21T07:28:48.470 に答える
0

理論的には、ディレクトリの「変更された」タイムスタンプをチェックすることで、処理を高速化できます。ディレクトリが変更されていない場合、そのディレクトリ内のファイルを確認する必要はありません。残念ながら、可能性のあるサブディレクトリをスキャンする必要があります。それらを見つけるには、ディレクトリをスキャンする必要があります...ディレクトリツリー構造を保存していない限り。

そしてもちろん、10 億個のファイルを含むフラットなディレクトリがある場合、これは意味がありません。


データベースにクエリを実行する前にそれらをソートできるように、メモリ内のすべてのファイルパスを組み立てていると思います。(そして、それらをソートすることは良い考えです...)しかし、メモリ内でソートする代わりの方法があります:

  1. ファイルパスをファイルに書き込みます。
  2. 外部の並べ替えユーティリティを使用して、ファイルを主キー順に並べ替えます。
  3. ソートされたファイルを読み取り、キー順にデータベースに対してバッチ クエリを実行します。

(ディスクに本当に 10 億個のファイルがありますか? それはデータ ストアの設計が悪いように思えます...)

于 2012-05-21T07:00:03.707 に答える
0

メモリが重要な場合は、オペレーティング システムの機能を使用します。

ext4 を使用している場合は、Unix を使用していると想定します (Win などの他のオペレーティング システムに find をインストールできます)。このような場合は、ネイティブの find コマンドを使用できます (これは最終的なものになります。もちろん、最後のスキャン時刻を覚えていて、これを好きなように変更できます): find /directory_path -type f -mtime -1 -印刷する

もちろん、削除はありません。ヒューリスティック アルゴリズムが機能する場合は、データベースに保存されている各ファイル (最初に表示する必要があるもの、次に新しいものから古いものへ) にゆっくりと移動するスレッドを作成し、それがまだオンラインであることを確認できます。これは多くのメモリを消費しません。とにかく、10 億個のファイルをユーザーに表示することはできないと思います。

于 2012-07-05T11:52:03.883 に答える
0

削除が発生したときに削除されるもののリストはありますか (または、これを作成するために削除するプロセスを変更します)? もしそうなら、タイムスタンプ付きの「私は削除されました」のリストを作成し、このリストからアイテムを選択して、変更されたものだけを同期することはできませんか? 当然、サーバーの処理速度が遅い時間帯に何らかのバッチ ジョブを同期させたいと思うでしょうが、それによって負荷を軽減できると思います。

別のオプションは、コードの変更内容に応じて、そのプロセスが削除時にデータベースを直接更新することです (複数のノードがある場合)。これにより、システムに何らかの結合が導入されますが、これが最も効率的な方法です。

私の意見では、削除が発生したというメッセージのアイデアのいくつかのバリエーション(それが最近削除されたファイルのリストを使用してどこかに書き込むだけのファイルであっても)、または何らかの直接コールバックメカニズムのいずれかです。コードを使用するか、アプリケーションが削除プロセスから直接使用する永続データ ストアを調整するだけです。

以上のことをすべて述べたとしても、すべてが正しく一致していることを確認するために、何らかの種類のインデックス同期またはインデックスの定期的な健全性チェックを常に行う必要があります。

ファイル スペースを、たとえば 1 フォルダーあたり 5,000 ~ 10,000 個のファイルでフォルダーに分割し、次のような単純なファイルを作成することができます (そして、所有しているファイルの数に基づいて作成する必要がなければ、私はショックを受けます)。フォルダー内のすべてのファイルの名前のハッシュがあります。これは削除をキャッチしますが、削除が発生したときに何らかの形で直接コールバックする方がはるかに優れていると思います。これらすべてのものを含むモノリシックなフォルダーがある場合は、それを個別のフォルダーに分割する何かを作成すると (メインフォルダーの下に単純な番号を使用したため、面倒なことに進むことができました)、すべてが大幅に高速化されます。すべての新しいファイルに対してこれを実行し、古いファイルをそのままにしておく必要がある場合でも、少なくともファイルの取得時に出血を止めることができます.

私の意見では、ファイルのインデックスをプログラムで制御しているため、基本的なファイル システムへの変更時に変更が発生した場合は、変更を許可するのではなく、何らかの方法で同じプログラムを関与させる (または通知する) 必要があります。次に、すべてを調べて更新を探します。当然のことながら、この通信が途切れる異常値を検出するには、ファイル システムの内容を実際にチェックし、インデックスを定期的に更新するための同期コードをそこに含める必要があります (ただし、これはメイン アプリケーションのプロセス外でバッ​​チ処理する必要があります)。 )。

于 2012-07-05T11:21:21.103 に答える