V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
1yndonn3u
V2EX  ›  MongoDB

MongoDB 复合索引在单独查询字段的时候不生效。

  •  
  •   1yndonn3u · 2015-12-26 14:52:18 +08:00 · 6160 次点击
    这是一个创建于 3237 天前的主题,其中的信息可能已经有所发展或是发生改变。

    数据如下:

    > db.testcoll.find().limit(2)
    { "_id" : ObjectId("567ac8e9498f43a9cea8dd08"), "Name" : "User1", "Age" : 1, "Gender" : "M", "PreferBooks" : [ "frist book", "Second book" ] }
    { "_id" : ObjectId("567ac8e9498f43a9cea8dd09"), "Name" : "User2", "Age" : 2, "Gender" : "M", "PreferBooks" : [ "frist book", "Second book" ] }
    

    索引如下:

    > db.testcoll.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "_id" : 1
            },
            "name" : "_id_",
            "ns" : "testdb.testcoll"
        },
        {
            "v" : 1,
            "unique" : true,
            "key" : {
                "Name" : 1
            },
            "name" : "Name_1",
            "ns" : "testdb.testcoll"
        },
        {
            "v" : 1,
            "key" : {
                "Name" : 1,
                "Age" : 1
            },
            "name" : "Name_1_Age_1",
            "ns" : "testdb.testcoll"
        }
    ]
    >
    

    从索引里面看到有 Name:1,Age:1 的复合索引。查询单独 Age 数据:

    > db.testcoll.find({Age:{$gt:80}}).hint("Name_1_Age_1").explain()
    {
        "cursor" : "BtreeCursor Name_1_Age_1",
        "isMultiKey" : false,
        "n" : 21,
        "nscannedObjects" : 99,
        "nscanned" : 99,
        "nscannedObjectsAllPlans" : 99,
        "nscannedAllPlans" : 99,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
            "Name" : [
                [
                    {
                        "$minElement" : 1
                    },
                    {
                        "$maxElement" : 1
                    }
                ]
            ],
            "Age" : [
                [
                    {
                        "$minElement" : 1
                    },
                    {
                        "$maxElement" : 1
                    }
                ]
            ]
        },
        "server" : "junmao.local:27019",
        "filterSet" : false
    }
    >
    

    上面结果显示的为什么 age 字段没有使用复合索引呢?麻烦请教下大家,复合索引创建在 Name:1 和 Age:1 的时候不是相当于 Name 和 Age 的都创建了么,查询 Age 数据最起码的应该是对 Age 进行索引啊,我查询 user 的时候是可以索引的,如下

    > db.testcoll.find({Name:"User233"}).hint("Name_1_Age_1").explain()
    {
        "cursor" : "BtreeCursor Name_1_Age_1",
        "isMultiKey" : false,
        "n" : 0,
        "nscannedObjects" : 0,
        "nscanned" : 0,
        "nscannedObjectsAllPlans" : 0,
        "nscannedAllPlans" : 0,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
            "Name" : [
                [
                    "User233",
                    "User233"
                ]
            ],
            "Age" : [
                [
                    {
                        "$minElement" : 1
                    },
                    {
                        "$maxElement" : 1
                    }
                ]
            ]
        },
        "server" : "junmao.local:27019",
        "filterSet" : false
    }
    >
    

    同时查询 Name 和 Age :

    > db.testcoll.find({Name:"User233",Age:233}).hint("Name_1_Age_1").explain()
    {
        "cursor" : "BtreeCursor Name_1_Age_1",
        "isMultiKey" : false,
        "n" : 0,
        "nscannedObjects" : 0,
        "nscanned" : 0,
        "nscannedObjectsAllPlans" : 0,
        "nscannedAllPlans" : 0,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
            "Name" : [
                [
                    "User233",
                    "User233"
                ]
            ],
            "Age" : [
                [
                    233,
                    233
                ]
            ]
        },
        "server" : "junmao.local:27019",
        "filterSet" : false
    }
    >
    

    复合索引也使用最左匹配法则了?

    mongo version

    MongoDB shell version: 2.6.11
    

    真心请教

    3 条回复    2015-12-29 12:19:05 +08:00
    tracymcladdy
        1
    tracymcladdy  
       2015-12-26 19:29:10 +08:00
    单独查询字段单独建索引
    1yndonn3u
        2
    1yndonn3u  
    OP
       2015-12-27 22:45:11 +08:00
    @tracymcladdy 复合索引不是相当于两条索引么?
    1yndonn3u
        3
    1yndonn3u  
    OP
       2015-12-29 12:19:05 +08:00
    @tracymcladdy 网上部分资料有问题,复合索引也是单独的索引。最左匹配原则,最左的相当于章,而第二个字段相当于节。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3315 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 00:39 · PVG 08:39 · LAX 16:39 · JFK 19:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.