2017-07-11 26 views
0

私は現在動作している以下のコードを持っています。それは通過し、指定された日付よりも新しいすべてのファイルを見つけ、正規表現にマッチしてそれを削除し、それを指しているチャンクも削除します。MongoDBから大量のデータを削除する

conn = new Mongo("<url>"); 
db = conn.getDB("<project>"); 

res = db.fs.files.find({"uploadDate" : { $gte : new ISODate("2017-04-04")}}, {filename : /.*(png)/}); 
while (res.hasNext()) { 
    var tmp = res.next(); 
    db.getCollection('fs.chunks').remove({"files_id" : tmp._id}); 
    db.fs.files.remove({ "_id" : tmp._id}); 
} 

これは非常に遅く、ほとんどの場合、クライアントはただ時間切れから実行しています。

また、私はファイルシステムからファイルを削除していて、通常のコレクションからは削除していないことを知っています。長い話ですが、上記のコードはまさに私がしたいことです。

これをより速く実行するにはどうすればよいですか? 私はこのコードをクライアント上で実行していることを以前に指摘されましたが、サーバー側で実行することは可能ですか? Javascriptドライバを使用する前に、おそらくこれが原因です。私は、Mongoシェルを使ってサーバ上のeverythinを実行すると仮定します。

ご協力いただければ幸いです。私は、ファイルシステムからファイルを削除てることを知っているので、近いが、これまで...

+0

downvotes ... – justynnuff

答えて

2

はなく、通常のコレクションから

GridFSので、MongoDBの中にバイナリデータを格納するための仕様ですファイルシステムからのファイルではなくMongoDBコレクションから実際に文書を削除しています。

私はこのコードをクライアントで実行していることが以前に私に指摘されましたが、サーバー側で実行することは可能ですか?

あなたのコード(クエリとコマンド)の大半はMongoDBサーバーによって実行されています。クライアント(この場合シェルmongo)は重要な処理を行っていません。

これは非常に遅く、ほとんどの場合、クライアントはただ時間切れから実行しています。

時間の所在を調査する必要があります。

あなたmongoシェルと配備の間に問題のあるネットワークの遅延がある場合、あなたは(可能な場合)に近い展開にmongoシェルセッションからクエリを実行することを検討や文書の小さな範囲に一致するクエリ条件を使用することができます。

もう1つの明らかな候補は、サーバーリソースです。たとえば、I/OやRAMに負荷をかけている文書を大量に削除していますか?この場合、各スクリプト実行で削除するドキュメントの数を減らすことも役立ちます。

db.fs.files.find({ "uploadDate":{$ GTE:新しいISODate( "2017年4月4日")}}、{ファイル名:/.*(png)/})

このクエリでは、おそらくあなたが意図したものでやっていません:filenamefind()に2番目のオプションとして提供されている(その投影ではなく、検索条件のために使用されている)と正規表現は、例えばどこにでもpngを(含むファイル名に一致します:typng.doc)。

私は、Mongoシェルを使用してサーバー上のすべてを実行すると仮定します。

これは間違った一般的な仮定です。 mongoシェルはローカル関数を評価することができるので、コードに応じて、サーバーコンテキストではなくクライアントコンテキストで実行/評価されるアスペクトが存在する可能性があります。サーバー上で処理されるクエリ/コマンドがサンプルコードで実行されていますが、クエリから返されたドキュメントがmongoシェルでアクセスされ、fs.chunksの関連ドキュメントを削除するクエリが作成されています。

これをより速く実行するにはどうすればよいですか?

上記のコメントに加えて、効率性を向上させるためにいくつかのコード変更があります。特に、チャンク文書を個別に削除しています。 MongoDB 2.6+にはBulk APIがあり、削除のバッチごとに必要な往復を減らします。速度を改善しようとする

いくつかの追加提案:

  • はあなたのfind()クエリをサポートするために、{uploadDate:1, filename: 1}にインデックスを追加します。

    db.fs.files.createIndex({uploadDate:1, filename: 1}) 
    
  • ではなく、一致チャンクドキュメントを削除するためにバルクAPIを使用して、個人よりも:

    while (res.hasNext()) { 
        var tmp = res.next(); 
        var bulk = db.fs.chunks.initializeUnorderedBulkOp(); 
        bulk.find({"files_id" : tmp._id}).remove(); 
        bulk.execute(); 
        db.fs.files.remove({ "_id" : tmp._id}); 
    } 
    
  • はあなたが必要なフィールドを含めるにfs.filesクエリに射影を追加します。

    var res = db.fs.files.find(
        // query criteria 
        { 
         uploadDate: { $gte: new ISODate("2017-04-04") }, 
    
         // Filenames that end in png 
         filename: /\.png$/ 
        }, 
    
        // Only include the _id field 
        { _id: 1 } 
    ) 
    

    注:あなたがGridFSファイルにメタデータの多くを追加(または削除するファイルをたくさん持っている)していない限り、この重要な影響を及ぼさないかもしれない。デフォルトのfs.filesドキュメントは〜130バイトですが、必要なフィールドは_id(12バイトのObjectId)です。

関連する問題