0

私はmongoの新しいユーザーです(mysqlの豊富な経験があります)。興味深い長所と短所があるようです。長所は、明らかに、保持できるデータのサイズと、レコードを書き込む速度です。コレクションに多くのログを書き込むアプリケーションがあり、これまでに約 7m あります。私の問題は、一見単純なクエリに非常に長い時間がかかることです。説明させてください。

私のコレクションには 700 万のドキュメントがあります。

> db.alpha2.count()
7257619

ここで、特定の cid のすべてのレコードをカウントしたいのですが、そのタイムスタンプは特定の数値よりも小さくなっています (この例では、将来のタイムスタンプがあるため、すべてをカウントする必要があります)。

> db.alpha2.find({'ts': {'$lt': 1446457607}, 'cid': '2636518'}).count()
7257619

これが問題のクエリです。この数値を返すのに58 秒かかります。概念的には、これは非常に単純なクエリであり、SQL の世界では次のようになります。

select count(*) from alpha2 where cid=2636518 and ts<1446457607

同等のテーブルはありませんが、私の経験に基づいて、mysql で実行するのに 0.1 秒もかからないと思います。それで、私は何をしますか?7m レコードをはるかに超えるデータセットで、多くの集計を行う予定です。私はまた、少し難しいこと(マップの縮小)も行っていますが、それははるかに悪いことです(数分)。これを 1 秒未満にする必要があります。私は何を間違っていますか?この時間はmongoで予想されますか?

上記のクエリのタイミングの前に、これを使用して ts 値にインデックスを付けます。

db.alpha2.ensureIndex({ts:1})
4

1 に答える 1

4

を特定するためにcount()、MongoDB は一致するすべてのドキュメントを見つける必要があります。

クエリをExplain()して、インデックスがどのように使用されているかを確認できます。

 db.alpha2.find({'ts': {'$lt': 1446457607}, 'cid': '2636518'}).explain()

nscannedObjects特に、 (スキャンされるドキュメントの数)を最小限に抑えたいと考えています。

最良の標準的なシナリオは、カウントに含まれるすべてのフィールドにインデックスを付けることです (そして、インデックスが利用可能な RAM に収まるようにします)。

cidしたがって、インデックスには次のものも含める必要があります。

 db.alpha2.ensureIndex({ts:1, cid:1})

頻繁にカウントを行っている場合は、ユースケースで機能する場合は、インクリメンタルマップ/リデュースなどのプロセスを介してこれらを保存および更新することをお勧めします。

于 2012-09-12T00:15:12.820 に答える