【问题标题】:Mongodb using wrong indexMongodb使用错误的索引
【发布时间】:2014-04-25 07:14:23
【问题描述】:

我在一个集合上有多个索引,如下所示。特别是我希望查询使用"gTs_1_RE_H_1_l_1",但查询使用的是"gTs_1"

{
    "0" : {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "ns" : "week_raw_tweet_db.tweets",
        "name" : "_id_"
    },
    "1" : {
        "v" : 1,
        "key" : {
            "gTs" : 1
        },
        "ns" : "week_raw_tweet_db.tweets",
        "name" : "gTs_1",
        "expireAfterSeconds" : 604800
    },
    "2" : {
        "v" : 1,
        "key" : {
            "uN" : 1
        },
        "ns" : "week_raw_tweet_db.tweets",
        "name" : "uN_1"
    },
    "3" : {
        "v" : 1,
        "key" : {
            "gTs" : 1,
            "RE_H" : 1,
            "l" : 1
        },
        "ns" : "week_raw_tweet_db.tweets",
        "name" : "gTs_1_RE_H_1_l_1",
        "background" : 1
    }
}

这里我有一个单独的“gTs”索引(基于 TTL 的索引)和一个以“gTs”和“RE_H”作为前两个键的复合索引。 ("gTs_1_RE_H_1_l_1")

现在,我正在尝试执行此查询:

db.tweets.find( {

                    "RE_H" : NumberLong("484001755192636620"),                  
                    "gTs" : {
                        "$lte" : ISODate("2014-03-18T22:00:00Z"),
                        "$gte" : ISODate("2014-03-17T21:00:00Z")
                    }
                }).explain()

据我所知,这应该使用"gTs_1_RE_H_1_l_1",但令人惊讶的是它正在使用, "gTs_1" 如此输出所提到的:

{
    "cursor" : "BtreeCursor gTs_1",
    "isMultiKey" : false,
    "n" : 46508,
    "nscannedObjects" : 365746,
    "nscanned" : 365746,
    "nscannedObjectsAllPlans" : 370493,
    "nscannedAllPlans" : 370494,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 1,
    "nChunkSkips" : 0,
    "millis" : 1509,
    "indexBounds" : {
        "gTs" : [ 
            [ 
                ISODate("2014-03-17T21:00:00.000Z"), 
                ISODate("2014-03-18T22:00:00.000Z")
            ]
        ]
    },
    "server" : "Frrole-API1:27017"
}

但是,如果我提供提示,它确实会选择正确的索引。所以,如果我运行以下查询:

db.tweets.find( {

                    "RE_H" : NumberLong("484001755192636620"),                  
                    "gTs" : {
                        "$lte" : ISODate("2014-03-18T22:00:00Z"),
                        "$gte" : ISODate("2014-03-17T21:00:00Z")
                    }
                }).hint("gTs_1_RE_H_1_l_1").explain()

我得到以下输出:

/* 0 */
{
    "cursor" : "BtreeCursor gTs_1_RE_H_1_l_1",
    "isMultiKey" : true,
    "n" : 46508,
    "nscannedObjects" : 233224,
    "nscanned" : 233541,
    "nscannedObjectsAllPlans" : 233224,
    "nscannedAllPlans" : 233541,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 3,
    "nChunkSkips" : 0,
    "millis" : 1874,
    "indexBounds" : {
        "gTs" : [ 
            [ 
                true, 
                ISODate("2014-03-18T22:00:00.000Z")
            ]
        ],
        "RE_H" : [ 
            [ 
                NumberLong(484001755192636620), 
                NumberLong(484001755192636620)
            ]
        ],
        "l" : [ 
            [ 
                {
                    "$minElement" : 1
                }, 
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "Frrole-API1:27017"
}

有人可以帮我了解发生了什么吗!

【问题讨论】:

    标签: mongodb mongodb-indexes compound-index


    【解决方案1】:

    从输出中可以看出,使用更简单索引的查询大约 300 毫秒,这就是 mongodb 使用该索引的原因。 MongoDB 的优化不会尝试了解查询路径并猜测它的速度,它只是执行不同的查询并测量哪个查询最快。您的 MongoDB 已经了解到使用简单的 gTs 索引会更快。它会不时地通过并行运行不同的查询来自动测试。

    据我所知,这应该使用“gTs_1_RE_H_1_l_1”,但令人惊讶的是,它使用的是“gTs_1”,如此输出中提到的:

    这并不奇怪。您应该查看有关索引的文档,特别是 the section about sorting。虽然您在这里没有请求排序,但您使用的是范围查询($lte 及其兄弟姐妹),这非常相似。您至少需要将索引的顺序更改为 RE_HgTs,以便先出现 equals 约束的索引,然后是范围查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-16
      • 2013-06-09
      • 2014-04-16
      • 2017-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      相关资源
      最近更新 更多