MongoDB 多键索引

来源:互联网 发布:如何上google 知乎 编辑:程序博客网 时间:2024/06/05 06:09

在MongoDB中可以基于数组来创建索引。MongoDB为数组每一个元素创建索引值。多键索引支持数组字段的高效查询。多键索引能够基于字符串,数字数组以及嵌套文档进行创建。本文主要描述多键索引并给出演示示例。

一、多键索引

    基于一个数组创建索引,MongoDB会自动创建为多键索引,无需刻意指定    多键索引也可以基于内嵌文档来创建    多键索引的边界值的计算依赖于特定的规则    注,多键索引不等于在文档上的多列创建索引(复合索引)    创建语法            db.coll.createIndex( { <field>: < 1 or -1 > } )    复合多键索引            对于一个复合多键索引,每个索引最多可以包含一个数组。            在多于一个数组的情形下来创建复合多键索引不被支持。    假定存在如下集合            { _id: 1, a: [ 1, 2 ], b: [ 1, 2 ], category: "AB - both arrays" }    不能基于一个基于{ a: 1, b: 1 }  的多键索引,因为a和b都是数组    假定存在如下集合            { _id: 1, a: [1, 2], b: 1, category: "A array" }            { _id: 2, a: 1, b: [1, 2], category: "B array" }            则可以基于每一个文档创建一个基于{ a: 1, b: 1 }的复合多键索引            原因是每一个索引的索引字段只有一个数组    一些限制            不能够指定一个多键索引为分片片键索引            哈希索引不能够成为多键索引            多键索引不支持覆盖查询    基于整体查询数组字段            当一个查询筛选器将一个数组作为整体实现精确匹配时,MongoDB可以使用多键索引查找数组的第一个元素,            但不能使用多键索引扫描寻找整个数组。相反,使用多键索引查找查询数组的第一个元素后,MongoDB检索            相关文档并且过滤出那些复合匹配条件的文档。                       

二、示意图

如下图,基于集合上的数组创建多键索引,且数组为内嵌文档
多键索引

三、创建多键索引

1、演示环境

    > db.version()    3.2.10    >db.inventory.insertMany([    { _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] },    { _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] },    { _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] },    { _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] },    { _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }])    //下面基于ratings列创建一个多键索引    > db.inventory.createIndex( { ratings: 1 } )    {            "createdCollectionAutomatically" : false,            "numIndexesBefore" : 1,            "numIndexesAfter" : 2,            "ok" : 1    }    //查询数组上为5,9的文档    > db.inventory.find( { ratings: [ 5, 9 ] } )    { "_id" : 6, "type" : "food", "item" : "bbb", "ratings" : [ 5, 9 ] }    //下面查看其执行计划    > db.inventory.find( { ratings: [ 5, 9 ] } ).explain()    {     "queryPlanner" : {           ........             "inputStage" : {                     "stage" : "IXSCAN",                     "keyPattern" : {                             "ratings" : 1                     },                     "indexName" : "ratings_1",                     "isMultiKey" : true,   //这里表明查询使用到了多键索引                      .......                     "direction" : "forward",                     "indexBounds" : {                             "ratings" : [                                     "[5.0, 5.0]",                                     "[[ 5.0, 9.0 ], [ 5.0, 9.0 ]]"          ..........     "ok" : 1    }    //在上面的示例中,使用了多键索引进行扫描,MongoDB寻找在ratings数组任意位置包含5的文档    //然后MongoDB检索这些文档,并过滤出那些等于[ 5, 9 ]的文档

2、基本索引数组

    假定存在下列集合    { _id: 1, item: "ABC", ratings: [ 2, 5, 9 ] }    在ratings上创建索引    db.survey.createIndex( { ratings: 1 } )    这个多键索引则包括2,5,9三个索引键,每一个分别指向相同的文档

3、基于内嵌文档的索引数组

    //创建演示文档    > db.inventory.drop()    > db.inventory.insertMany([    {      _id: 1,      item: "abc",      stock: [        { size: "S", color: "red", quantity: 25 },        { size: "S", color: "blue", quantity: 10 },        { size: "M", color: "blue", quantity: 50 }      ]    },    {      _id: 2,      item: "def",   // Author : Leshami      stock: [       // Blog   : http://blog.csdn.net/leshami        { size: "S", color: "blue", quantity: 20 },        { size: "M", color: "blue", quantity: 5 },        { size: "M", color: "black", quantity: 10 },        { size: "L", color: "red", quantity: 2 }      ]    },    {      _id: 3,      item: "ijk",      stock: [        { size: "M", color: "blue", quantity: 15 },        { size: "L", color: "blue", quantity: 100 },        { size: "L", color: "red", quantity: 25 }      ]    }])    //下面基于内嵌文档的2个键来创建索引    > db.inventory.createIndex( { "stock.size": 1, "stock.quantity": 1 } )    {            "createdCollectionAutomatically" : false,            "numIndexesBefore" : 1,            "numIndexesAfter" : 2,            "ok" : 1    }    //查询内嵌文档stock.size为M的执行计划    > db.inventory.find( { "stock.size": "M" } ).explain()    {     "queryPlanner" : {        ........        "winningPlan" : {                "stage" : "FETCH",                "inputStage" : {                        "stage" : "IXSCAN",  //基于索引的扫描                        "keyPattern" : {                                "stock.size" : 1,                                "stock.quantity" : 1                        },                        "indexName" : "stock.size_1_stock.quantity_1",                           .......                        "indexBounds" : {                                "stock.size" : [                                        "[\"M\", \"M\"]"                                ],                                "stock.quantity" : [                                        "[MinKey, MaxKey]"                                ]                        }                }        },    }    //基于内嵌文档2个键查询的执行计划    > db.inventory.find( { "stock.size": "S", "stock.quantity": { $gt: 20 } } ).explain()    {     "queryPlanner" : {       ..........       "winningPlan" : {               "stage" : "FETCH",               "filter" : {                       "stock.quantity" : {                               "$gt" : 20                       }               },               "inputStage" : {                       "stage" : "IXSCAN",  //此时同样也使用到了索引扫描                       "keyPattern" : {                               "stock.size" : 1,                               "stock.quantity" : 1                       },                       "indexName" : "stock.size_1_stock.quantity_1",                       "isMultiKey" : true,                        .........                       "indexBounds" : {                               "stock.size" : [                                       "[\"S\", \"S\"]"                               ],                               "stock.quantity" : [                                       "[MinKey, MaxKey]"               ............     "ok" : 1    }    //基于内嵌数组排序查询    > db.inventory.find( ).sort( { "stock.size": 1, "stock.quantity": 1 } ).explain()    {            "queryPlanner" : {                    ........                    "winningPlan" : {                            "stage" : "FETCH",                            "inputStage" : {                                    "stage" : "IXSCAN", //内嵌数组排序查询也使用到了索引                                    "keyPattern" : {                                            "stock.size" : 1,                                            "stock.quantity" : 1                                    },                                    "indexName" : "stock.size_1_stock.quantity_1",                                    "isMultiKey" : true,                                     ...........                                    "indexBounds" : {                                            "stock.size" : [                                                    "[MinKey, MaxKey]"                                            ],                                            "stock.quantity" : [                                                    "[MinKey, MaxKey]"                                            ]                                    }                            }                    },                    "rejectedPlans" : [ ]            },    }    //基于内嵌数组一个键作为过滤,一个键作为排序查询的执行计划    > db.inventory.find( { "stock.size": "M" } ).sort( { "stock.quantity": 1 } ).explain()    {     "queryPlanner" : {       ..........       "winningPlan" : {               "stage" : "FETCH",               "inputStage" : {                       "stage" : "IXSCAN",                       "keyPattern" : {                               "stock.size" : 1,                               "stock.quantity" : 1                       },                       "indexName" : "stock.size_1_stock.quantity_1",                       "isMultiKey" : true,                       "isUnique" : false,                       "isSparse" : false,                       "isPartial" : false,                       "indexVersion" : 1,                       "direction" : "forward",                       "indexBounds" : {                               "stock.size" : [                                       "[\"M\", \"M\"]"                               ],                               "stock.quantity" : [                                       "[MinKey, MaxKey]"       "rejectedPlans" : [ ]       .......     "ok" : 1    }

更多参考
MongoDB 单键(列)索引
MongoDB 复合索引
MongoDB执行计划获取(db.collection.explain())
DBA牛鹏社(SQL/NOSQL/LINUX)

0 0
原创粉丝点击