1

私は多くのドキュメント(多分数百万)を持つコレクションを持っています。ユーザーが新しいドキュメントを挿入するときに、インデックスを作成できるデータの「順序」を維持するフィールドが必要です。たとえば、1つのフィールドが時間の場合、この形式「1352392957.46516」で、3つのドキュメントがある場合、最初のドキュメントは時間1352392957.46516、2番目のフィールドは時間1352392957.48516(20ミリ秒後)、3番目のドキュメントは1352392957.49516(10ミリ秒後)になります。最初のドキュメントが0で、2番目が1、3番目が2というようになる別のフィールドが必要です。

これが必要な理由は、そのフィールドにインデックスを付けることができるようにするためです。次に、検索を実行するときに、効率的な$mod演算を実行してデータをダウンサンプリングできます。したがって、たとえば、100万のドキュメントがあり、そのうちの1000だけを等間隔で配置したい場合は、整数フィールドで$ mod [1000、0]を実行できます。

時間フィールドでそれを実行できなかった理由は、それらが完全に間隔を空けていないか、すべてが偶数または奇数であるためにmodが機能しない可能性があるためです。したがって、個別の整数フィールドは、線形に増加する方法で順序を維持します。

また、コレクション内のどこにでもドキュメントを挿入できる必要があるため、後続のすべてのフィールドを更新する必要があります。

これを自動的に行う方法はありますか?それとも私はこれを実装する必要がありますか?それとも、私が説明していることを行うためのより効率的な方法はありますか?

4

1 に答える 1

1

1 回の挿入で数百万のドキュメントを更新する場合、「遅い挿入」をはるかに超えています。この方法では、コレクション全体がアクティブなワーキング セットになります。同様に、$modキー値と比較するには、インデックス内のすべてのキー値を比較する必要があります。

ソートされたサンプリング順序の要件を考えると、より効率的な事前集計アプローチがあるかどうかはわかりません。

skip()andlimit()を使用して、ランダムなドキュメントをフェッチします。このskip()コマンドは、毎回不要なドキュメントをスキップするためにインデックスの先頭からスキャンしますが、インデックスをメモリに保持するのに十分な RAM があれば、パフォーマンスは許容できるはずです。

// Add an index on time field
db.data.ensureIndex({'time':1})

// Count number of documents
var dc = db.data.count()

// Iterate and sample every 1000 docs
var i = 0; var sampleSize = 1000; var results = [];
while (i < dc) {
    results.push(db.data.find().sort({time:1}).skip(i).limit(1)[0]);
    i += sampleSize;
}

// Result array of sampled docs
printjson(results);
于 2012-11-08T20:13:56.307 に答える