MongoDB 复合索引

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                       
 

MongoDB支持复合索引,即将多个键组合到一起创建索引。该方式称为复合索引,或者也叫组合索引,该方式能够满足多键值匹配查询使用索引的情形。其次复合索引在使用的时候,也可以通过前缀法来使用索引。MongoDB中的复合索引与关系型数据库基本上一致。在关系型数据库中复合索引使用的一些原则同样适用于MongoDB。本文主要描述MongoDB复合索引。

一、复合索引相关概述

1、复合索引创建语法        db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )        同创建单键(列)索引一样,索引创建时需要指定每一个键索引的顺序        多个键直接用逗号分隔        索引创建语法可以参考:http://blog.csdn.net/leshami/article/details/535419782、复合索引的一些特性        复合索引可以支持要求匹配多个键的查询        复合索引每一个键的顺序非常重要,这将决定该索引在查询过程中能否被使用到        复合索引支持前导(缀)列索引查询        不能够创建基于哈希索引类型的复合索引        任意复合索引字段不能超过31
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

二、复合索引示意图

如下图所示,在集合的userid以及score列上创建一个复合索引,其中userid为升序,score为降序
这里写图片描述

三、复合索引示例

1、演示环境

> db.version()3.2.10> db.example.find({},{"_id":0}){ "id" : 1, "ename" : "leshami", "blog" : "http://blog.csdn.net/leshami", "name" : "leshami" }演示集合数据,可以参考:http://blog.csdn.net/leshami/article/details/52672310//查看任意的一个文档> db.persons.find().limit(1).pretty(){        "_id" : ObjectId("5812cbaaa129eed14b46458d"),        "name" : "robinson.cheng",        "age" : 25,        "email" : "[email protected]",        "score" : {                "c" : 89,                "m" : 96,                "e" : 87        },        "country" : "USA",        "books" : [                "JS",                "C++",                "EXTJS",                "MONGODB"        ]}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

2、创建复合索引

//如下示例,我们在集合persons上的name及age键上创建复合索引,且2个都为升序> db.persons.createIndex({name:1,age:1}){        "createdCollectionAutomatically" : false,        "numIndexesBefore" : 1,        "numIndexesAfter" : 2,        "ok" : 1}//在上面的示例中索引首先会按照name的值升序进行排列//其次是age键,在name之后也按照升序排列//下面过滤条件仅使用一个name键来查看执行计划> db.persons.find({name:"robinson.cheng"}).explain(){   ......   "stage" : "FETCH",   "inputStage" : {           "stage" : "IXSCAN"//使用索引扫描           "keyPattern" : {                   "name" : 1,                   "age" : 1           },           "indexName" : "name_1_age_1",             ......           "direction" : "forward",           "indexBounds" : {                   "name" : [                           "[\"robinson.cheng\", \"robinson.cheng\"]"                   ],                   "age" : [                           "[MinKey, MaxKey]"  ......... "ok" : 1}//下面过滤条件仅使用name及age键来查看执行计划> db.persons.find({name:"robinson.cheng",age:25}).explain(){                 .........                  "stage" : "FETCH",                 "inputStage" : {                         "stage" : "IXSCAN"//使用索引扫描                         "keyPattern" : {                                 "name" : 1,                                 "age" : 1                         },                         "indexName" : "name_1_age_1",                          .........                         "direction" : "forward",                         "indexBounds" : {                                 "name" : [                                         "[\"robinson.cheng\", \"robinson.cheng\"]"                                 ],                                 "age" : [                                         "[25.0, 25.0]"          ........... "ok" : 1}//下面过滤条件仅使用name及age键来查看执行计划,但是将age键放在name键之前> db.persons.find({age:25,name:"robinson.cheng"}).explain(){ "queryPlanner" : {      .....         "winningPlan" : {                 "stage" : "FETCH",                 "inputStage" : {                         "stage" : "IXSCAN"//使用索引扫描                         "keyPattern" : {                                 "name" : 1,                                 "age" : 1                         },                         "indexName" : "name_1_age_1",                          ...........                         "direction" : "forward",                         "indexBounds" : {                                 "name" : [                                         "[\"robinson.cheng\", \"robinson.cheng\"]"                                 ],                                 "age" : [                                         "[25.0, 25.0]"       ........ "ok" : 1}//下面单独基于age键作为过滤条件进行查询> db.persons.find({age:25}).explain(){         ................                "winningPlan" : {                        "stage" : "COLLSCAN"//此处为使用集合扫描方式                        "filter" : {                                "age" : {                                        "$eq" : 25                                }                        },                        "direction" : "forward"                },                "rejectedPlans" : [ ]         ..............        "ok" : 1}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

3、复合索引与排序

复合索引创建时按升序或降序来指定其排列方式。对于单键索引,其顺序并不是特别重要,因为MongoDB可以在任一方向遍历索引对于复合索引,按何种方式排序能够决定该索引在查询中能否被使用到。//以下内容基于前面在{name:1,age:1}键上创建的索引来考察这个复合索引在排序时被使用到的场景//基于{name:1,age:1}的排序> db.persons.find().sort({name:1,age:1}).explain(){    "queryPlanner" : {            ....            "winningPlan" : {                    "stage" : "FETCH",                    "inputStage" : {                            "stage" : "IXSCAN",   //索引扫描                            "keyPattern" : {                                    "name" : 1,                                    "age" : 1                            },                            "indexName" : "name_1_age_1",                             ..........                            "direction" : "forward",                            "indexBounds" : {                                    "name" : [                                            "[MinKey, MaxKey]"                                    ],                                    "age" : [                                            "[MinKey, MaxKey]"         ....    "ok" : 1}//基于{name:1,age:-1}的排序> db.persons.find().sort({name:1,age:-1}).explain(){    "queryPlanner" : {      ....            "winningPlan" : {                    "stage" : "SORT",                    "sortPattern" : {                            "name" : 1,                            "age" : -1                    },                    "inputStage" : {                            "stage" : "SORT_KEY_GENERATOR",                            "inputStage" : {                                    "stage" : "COLLSCAN", //集合扫描                                    "filter" : {                                            "$and" : [ ]                                    },                                    "direction" : "forward"       .........    "ok" : 1}//基于{name:-1,age:1}的排序> db.persons.find().sort({name:-1,age:1}).explain(){   "queryPlanner" : {           .........           "winningPlan" : {           "stage" : "SORT",           "sortPattern" : {                   "name" : -1,                   "age" : 1           },           "inputStage" : {                   "stage" : "SORT_KEY_GENERATOR",                   "inputStage" : {                           "stage" : "COLLSCAN",  //集合扫描                           "filter" : {                                   "$and" : [ ]                           },                           "direction" : "forward"      .........   "ok" : 1}//基于{age:1,name:1}的排序> db.persons.find().sort({age:1,name:1}).explain(){          ....         "inputStage" : {          "stage" : "SORT_KEY_GENERATOR",          "inputStage" : {                  "stage" : "COLLSCAN",  //集合扫描                  "filter" : {                          "$and" : [ ]                  },                  "direction" : "forward"         ..........  "ok" : 1}//基于{age:-1,name:1}的排序> db.persons.find().sort({age:-1,name:1}).explain(){   ..........   "inputStage" : {           "stage" : "SORT_KEY_GENERATOR",           "inputStage" : {                   "stage" : "COLLSCAN",    //集合扫描                   "filter" : {                           "$and" : [ ]                   },                   "direction" : "forward"   ..........  "ok" : 1}//基于{name:-1,age:-1}的排序> db.persons.find().sort({name:-1,age:-1}).explain(){      .........      "inputStage" : {              "stage" : "IXSCAN",      //索引扫描              "keyPattern" : {                      "name" : 1,                      "age" : 1              },              "indexName" : "name_1_age_1",              ............               "direction" : "backward", //注意,这里的方向为向后扫描              "indexBounds" : {                      "name" : [                              "[MaxKey, MinKey]"                      ],                      "age" : [                              "[MaxKey, MinKey]"    ...... "ok" : 1}通过上面的不同场景,得出如下:排序使用到索引的情形        db.persons.find().sort({name:1,age:1})        db.persons.find().sort({name:-1,age:-1})排序未使用到索引的情形        db.persons.find().sort({name:1,age:-1})        db.persons.find().sort({name:-1,age:1})        db.persons.find().sort({age:1,name:1})        db.persons.find().sort({age:-1,name:1})
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141

4、复合索引与索引前缀

    索引前缀指的是复合索引的子集    假如存在如下索引    { "item": 1, "location": 1, "stock": 1 }    那存在下列索引前缀    { item: 1 }    { item: 1, location: 1 }    在MongoDB中,下列查询过滤条件情形中,索引将会被使用到            item字段            item字段 + location字段            item字段 + location字段 + stock字段            item字段 + location字段(尽管索引被使用,但不高效)    以下过滤条件查询情形,索引将不会被使用到            location字段        stock字段        location + stock字段  
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

5、小结
a、复合索引是基于多个键(列)上创建的索引
b、复合索引在创建的时候可以为其每个键(列)来指定排序方法
c、索引键列的排序方法影响查询在排序时候的操作,方向一致或相反的才能被匹配
d、复合索引与前缀索引通常在匹配的情形下才能被使用

DBA牛鹏社(SQL/NOSQL/LINUX)

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/fsfsdfsdw/article/details/84195572