1

私は今朝の大半を MongoDBのdocsblog、およびスタック上の他の回答を再読することに費やしましたが、他の人にとって痛々しいほど明白であることを願っている何かがまだ欠けています。

編集: サブドキュメント (メタデータ.*) を持たないようにドキュメントのスキームを変更しましたが、インデックスがカバーされていないという問題がまだあります。既存のインデックスを削除し、新しいインデックスで再インデックスしました。

だから私は持っていません:

[
    {
        "v" : 1,
        "key" : {
                "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.daily"
    },
    {
        "v" : 1,
        "key" : {
                "host" : 1,
                "cid" : 1,
                "title" : 1,
                "urls" : 1,
                "global" : -1,
                "current" : -1,
                "total" : -1
        },
        "name" : "byHostTotals",
        "ns" : "test.daily"
    },
    {
        "v" : 1,
        "key" : {
                "host" : 1,
                "cid" : 1,
                "title" : 1,
                "urls" : 1,
                "total" : -1,
                "global" : -1,
                "current" : -1
        },
        "name" : "byHostCurrents",
        "ns" : "test.daily"
    }
]

そして、次のクエリが与えられます:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'current': -1}).limit(10).explain()

「byHostCurrent」という名前のインデックスでカバーされているものとして表示されません。

{
    "clauses" : [
        {
            "cursor" : "BtreeCursor byHostCurrents",
            "isMultiKey" : true,
            "n" : 10,
            "nscannedObjects" : 1090,
            "nscanned" : 1111,
            "scanAndOrder" : true,
            "indexOnly" : false,
            "nChunkSkips" : 0,
            "indexBounds" : {
                "host" : [
                        [
                            "example.com",
                            "example.com"
                        ]
                ],
                "cid" : [
                    [
                        {
                            "$minElement" : 1
                        },
                        {
                            "$maxElement" : 1
                        }
                    ]
                ],
                "title" : [
                    [
                        {
                            "$minElement" : 1
                        },
                        {
                            "$maxElement" : 1
                        }
                    ]
                ],
                "total" : [
                    [
                        {
                            "$maxElement" : 1
                        },
                        {
                            "$minElement" : 1
                        }
                    ]
                ],
                "global" : [
                    [
                        {
                            "$maxElement" : 1
                        },
                        {
                            "$minElement" : 1
                        }
                    ]
                ],
                "current" : [
                    [
                        {
                            "$maxElement" : 1
                        },
                        {
                            "$minElement" : 1
                        }
                    ]
                ]
            }
        },
        {
            "cursor" : "BtreeCursor ",
            "isMultiKey" : false,
            "n" : 0,
            "nscannedObjects" : 0,
            "nscanned" : 0,
            "scanAndOrder" : true,
            "indexOnly" : false,
            "nChunkSkips" : 0,
            "indexBounds" : {
                "host" : [
                        [
                                "usatoday.com",
                                "usatoday.com"
                        ]
                ],
                "cid" : [
                    [
                        {
                                "$minElement" : 1
                        },
                        {
                                "$maxElement" : 1
                        }
                    ]
                ],
                "title" : [
                    [
                        {
                                "$minElement" : 1
                        },
                        {
                                "$maxElement" : 1
                        }
                    ]
                ],
                "total" : [
                    [
                        {
                                "$maxElement" : 1
                        },
                        {
                                "$minElement" : 1
                        }
                    ]
                ],
                "global" : [
                    [
                        {
                                "$maxElement" : 1
                        },
                        {
                                "$minElement" : 1
                        }
                    ]
                ],
                "current" : [
                    [
                        {
                                "$maxElement" : 1
                            },
                            {
                                "$minElement" : 1
                            }
                        ]
                    ]
                }
            }
        ],
    "cursor" : "QueryOptimizerCursor",
    "n" : 10,
    "nscannedObjects" : 1090,
    "nscanned" : 1111,
    "nscannedObjectsAllPlans" : 1090,
    "nscannedAllPlans" : 1111,
    "scanAndOrder" : false,
    "nYields" : 8,
    "nChunkSkips" : 0,
    "millis" : 9,
    "server" : "ubuntu:27017",
    "filterSet" : false
}

MongoDB のバージョンは 2.6.3 です。

4

1 に答える 1

3

これがスキニーです...

クエリの場合:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'current': -1}).limit(10);

そこに .sort() がない場合はインデックスを使用しますが、現在ソートを使用しているため、インデックス付きフィールドの順序が重要になります。

上記のクエリでインデックスを使用するには、次のような新しいインデックスを作成する必要があります。

db.daily.ensureIndex({'current': -1, 'host': 1, 'cid': 1, 'title': 1}); 

このインデックスを配置すると、indexOnly: true が得られます。これは、総電流を逆順 (降順) で調べているためであり、「 host' = 'example.com' および制限要件。

したがって、クエリをサポートするには、合計で 4 つの追加のインデックスが必要でした。

  1. 最新の人がいるコンテンツIDを見つけるためのもの(上記のインデックス)
  2. 1 つは、最も多くの人が参加しているコンテンツ ID を見つけるためのものです (上記と同様ですが、合計: current:-1 ではなく、-1)。
  3. 1 つは、現在のホストで並べ替えられたコンテンツを検索するもので (以下のインデックスを参照)、
  4. 合計でソートされたホストごとにコンテンツを検索するもの (以下のようなもの)

    db.daily.ensureIndex({'ホスト': 1, '現在': -1, 'cid': 1, 'タイトル': 1});

そのため、MongoDB のドキュメントは、特に並べ替えの問題を見ると、これらのことについての説明があまり明確ではありません。彼らが言い足りないのは、並べ替えを使用する場合、等式クエリの後に接頭辞フィールドを含めるか、すべての接頭辞フィールドを含める必要があるということです。

たとえば、私の質問からの元のインデックスが与えられた場合:

db.daily.ensureIndex({"host" : 1, "cid" : 1, "title" : 1, "urls" : 1, "global" : -1, "current" : -1, "total" : -1});

クエリをインデックスでカバーしたい場合は、次のように変更する必要があります。

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'current': -1}).limit(10);

これに:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'cid':1, 'title':1, 'urls': 1, 'global: 1, 'current': -1}).limit(10);

これは私が欲しかったものではありません。

これが将来誰かに役立つことを願っています。

于 2014-08-07T17:01:27.013 に答える