3

Mongo Javaドライバーmongo-java-driver-2.8.0.jarを使用して、期待される構造に一致しないレコードを更新する単一のコレクション内のすべてのレコードにアクセスするGroovyスクリプトがあります。スクリプトはチャンピオンのように機能しますが、コレクションが実際に持っているよりも多くのレコードを処理する理由について頭を悩ませています。または、より正確には、dbCursore.hasNext()は、コレクションが実際に持っているよりも多くのレコードを繰り返し処理します。これは、スクリプトが更新するものを見つけた場合にのみ発生します。スクリプトが更新なしで実行される場合、処理される総数は正しいです。

hasNext()は「最初からやり直す」のですか、それともレコードが更新されている場合、レコードはイテレーション内で移動しますか?

これがコードです...

static def doIt( mongo, normalizer, isDryRun ) {
    def ttlProcessed = 0
    def ttlCandidates = 0
    def ttlUpdated = 0
    def lapCount = 0;
    def lapStartTime = System.currentTimeMillis();

    def db = mongo.getDB( "devices" )
    DBCollection dbCollection = db.getCollection( "profiles" )
    DBCursor dbCursor = dbCollection.find();
    while ( dbCursor.hasNext() ) {
        DBObject source = dbCursor.next();
        DBObject normalized = normalizer.normalize( source )
        // Only update if changed...
        if ( ! ( source.equals( normalized ) ) ) {
            ttlCandidates++
            if ( !isDryRun ) {
                BasicDBObject searchQuery = new BasicDBObject( "_id", normalized.get( "_id" ) )
                WriteResult result = dbCollection.update( searchQuery, normalized, false, false, WriteConcern.SAFE );
                ttlUpdated++
            }
        }
        ttlProcessed++;
        if ( ttlProcessed % 10000 == 0 ) {
            printErr "split: ${lapCount}, splitElapsed: ${calcElapsed( lapStartTime) } ms, elapsed: ${calcElapsed( startTime )} ms, processed: ${ttlProcessed}, candidates: ${ttlCandidates}, updated: ${ttlUpdated}"
            lapCount++
            lapStartTime = System.currentTimeMillis()
        }
    }
    printErr "split: ${lapCount}, splitElapsed: ${calcElapsed( lapStartTime) } ms, elapsed: ${calcElapsed( startTime )} ms, processed: ${ttlProcessed}, candidates: ${ttlCandidates}, updated: ${ttlUpdated}"
}

実行によってレコードが更新された場合、ttlProcessedが処理中のコレクションのカウントよりも高い値を取得するのはどうしてですか?

4

1 に答える 1

5

これは、更新によってドキュメントが移動するために発生する可能性があります(通常は成長のため)。ドキュメントが大きくなり、再度処理される場合、それは反復としてカウントされますが、更新がべき等であると仮定すると(私はテストしていません)、問題にはなりません。

懸念がある場合は、この$snapshot オプションを使用してこれを回避できます。私もこれを読むことをお勧めします:

http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database

これらの問題は基本的に、mongodumpやmongoexportなどのツールが_idインデックスをウォークする理由です(つまり$snapshot、デフォルトで使用されます)。

そもそも動きの防止を検討したい場合は、パディングファクターページのこのセクションをご覧ください。

http://www.mongodb.org/display/DOCS/Padding+Factor#PaddingFactor-ManualPadding

2.2には、compactコマンドの実行時にパディングを設定するオプションもあります。

http://docs.mongodb.org/manual/release-notes/2.2/#padding-specizable-on-compact-command

于 2012-08-27T16:20:53.453 に答える