7

だから私はmongoDBにいくつかのコレクションを持つ非常に単純なデータベースを持っています:

> show collections
Aggregates <-- count: 92
Users <-- count: 68222
Pages <-- count: 1728288847, about 1.1TB
system.indexes

Aggregatesコレクションはコレクションの集合体であり、Pages各ドキュメントは次のようになります。

> db.Aggregates.findOne()
{
        "_id" : ObjectId("50f237126ba71610eab3aaa5"),
        "daily_total_pages" : 16929799,
        "day" : 21,
        "month" : 9,
        "year" : 2011
}

とてもシンプルです。ただし、92 日間すべてを合計してページ読み込みの合計を取得してみましょうdaily page loads

>>> def get_total():
...     start = datetime.now()
...     print sum([x['daily_total_pages'] for x in c.Aggregates.find()])
...     end = datetime.now()
...     print (end-start).seconds
...
>>> get_total()
1728288847
43

43秒?!??!??!?!

これらの 92 の集計結果は非常に小さいです。それらをテキストファイルに保存することもできますが、これはクレイジーです。

それとも小さいですか?mongoによると、それらはディスク上でどれくらいの大きさですか?

> db.Aggregates.stats()
{
        "ns" : "c.AggregateResults",
        "count" : 92,
        "size" : 460250104,
        "avgObjSize" : 5002718.521739131,
        "storageSize" : 729464832,
        "numExtents" : 7,
        "nindexes" : 2,
        "lastExtentSize" : 355647488,
        "paddingFactor" : 1.0690000000000066,
        "systemFlags" : 1,
        "userFlags" : 0,
        "totalIndexSize" : 16352,
        "indexSizes" : {
                "_id_" : 8176,
                "date_1" : 8176
        },
        "ok" : 1
}

これらの小さな毎日の数字の合計で 438 メガバイト? それぞれ約 280 バイトなので、合計で最大 25 ~ 30kb になるはずです。したがって、ストレージは巨大で、クエリは非常に遅くなります。ディスク上で断片化される可能性はありますか? Pagesドキュメントを完全なコレクションに挿入した後、集計を作成しました。

誰でもこの狂気についての洞察を持っていますか? :O


編集: Jared によるより具体的な find() クエリで解決されました。Sammaye が提供した以下のビデオでも、非常に興味深いストレージの洞察が得られます。


編集 2: sys.getsizeof() を使用することは、ツリーを再帰しないため、ドキュメントのサイズを確認するための本当に信頼できない方法であることがわかりました。実際、私のドキュメントは非常に大きく、最善の方法はより具体的なクエリとして find({}, {'daily_page_loads'}) を使用することでした!

4

1 に答える 1

9

avgObjSize280 バイトの見積もりと一致しません。オブジェクトの平均サイズは約 5MB で、storageSize1GB 近くあります。メモリに制約がある場合、1 GB のファイルすべてにアクセスする必要があるクエリを実行すると、多くのページ フォールトが発生します。

圧縮を試みましたか?

db.runCommand({compact: 'Aggregates'})

または修理中ですか?

db.repairDatabase()

それでもうまくいかない場合は、ドキュメント全体をプルするのではなく、合計に必要なフィールドだけをプルバックしてみてください。これらのドキュメントは実際には 5MB であり、ネットワーク経由でデータをプルするのに時間が費やされている可能性があります。

def get_total():
    start = datetime.now()
    print sum([x['daily_total_pages'] for x in c.Aggregates.find({}, {"daily_total_pages": 1})])
    end = datetime.now()
    print (end-start).seconds
于 2013-01-17T18:46:36.923 に答える