MongoDB 第11章 MongoDB 索引

举报
许小强 发表于 2022/03/18 17:09:01 2022/03/18
【摘要】 索引

1、简介
MongoDB提供了多样性的索引支持,索引信息被保存在system.indexes中,且默认总是为_id创建索引,它的索引使用基本和MySQL的关系型数据库一样,其实可以这样说说,索引是凌驾于数据存储系统之上的另外一层系统,所以各种结构迥异的存储都有相同或者相似的索引实现及使用接口并不足为奇。

2、基础索引
在字段age上创建索引,1(升序),-1(降序)

>db.user.ensureIndex({age:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.user.getIndexes();
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.user"
        },
        {
                "v" : 1,
                "key" : {
                        "age" : 1
                },
                "name" : "age_1",
                "ns" : "test.user"
        }
]
> 

说明
上列中显示出来了一共有2个索引,其中_id是创建表的时候自动创建的索引,此索引是不能够被删除的。

当系统已有大量数据时,创建索引的过程是个非常耗时的过程,我们可以在后台执行,只需要制定background:true即可。

>db.user.ensureIndex({age:1},{background:true})

3、文档索引

索引可以任何类型的字段,甚至文档。

> db.factories.insert({name:"www",addr:{city:"BJ",state:"BEIJING"}});
WriteResult({ "nInserted" : 1 })

在addr列上创建索引
> db.factories.ensureIndex({addr:1});
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
下面的查询将会用到我们刚刚创建的索引
> db.factories.find({addr:{city:"BJ",state:"BEIJING"}});
{ "_id" : ObjectId("54a935b579ceadf5fa8e2ec1"), "name" : "www", "addr" : { "city" : "BJ", "state" : "BEIJING" } }
但是下面这个查询不会用到索引,因为查询的顺序跟索引建立的顺序不一样
> db.factories.find({addr:{state:"BEIJING",city:"BJ"}});


4、组合索引
跟其他数据库产品一样,MongoDB也是有组合索引的,下面我门将在addr.ctiy和addr.state上建立组合索引,当创建组合索引时,字段后面的1表示升序,-1表示降序,是用1还是用-1主要跟排序的时候或者指定范围内查询的时候有关的。

> db.factories.ensureIndex({"addr.city":1,"addr.state":1});
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}
>

此时下面查询都用到了这个索引
> db.factories.find({"addr.city":"BJ","addr.state":"BEIJING"});
{ "_id" : ObjectId("54a935b579ceadf5fa8e2ec1"), "name" : "www", "addr" : { "city" : "BJ", "state" : "BEIJING" } }
>
<span style="font-family:SimHei;font-size:14px;">> db.factories.find({"addr.city":"BJ"});
{ "_id" : ObjectId("54a935b579ceadf5fa8e2ec1"), "name" : "www", "addr" : { "city" : "BJ", "state" : "BEIJING" } }
>
<span style="font-family:SimHei;font-size:14px;">> db.factories.find().sort({"addr.city":1,"addr.state":1});
{ "_id" : ObjectId("54a935b579ceadf5fa8e2ec1"), "name" : "www", "addr" : { "city" : "BJ", "state" : "BEIJING" } }


<span style="font-family:SimHei;font-size:14px;">> db.factories.find().sort({"addr.city":1})
{ "_id" : ObjectId("54a935b579ceadf5fa8e2ec1"), "name" : "www", "addr" : { "city" : "BJ", "state" : "BEIJING" } }


5、唯一索引
只需要在ensureIndex命令中指定unique:true即可创建唯一索引,比如往表t4中插入两条记录:

> db.t4.insert({firstname:"wang",lastname:"wu"});
WriteResult({ "nInserted" : 1 })
> db.t4.insert({firstname:"wang",lastname:"liu"});
WriteResult({ "nInserted" : 1 })


在t4表中建立唯一索引
> db.t4.ensureIndex({firstname:1,lastname:1},{unique:true});
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
查看索引:
> db.t4.getIndexes();
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.t4"
        },
        {
                "v" : 1,
                "unique" : true,
                "key" : {
                        "firstname" : 1,
                        "lastname" : 1
                },
                "name" : "firstname_1_lastname_1",
                "ns" : "test.t4"
        }
]

6、强制使用索引
hint命令可以强制使用某个索引

> db.t5.insert({name:"wangwu",age:20});
WriteResult({ "nInserted" : 1 })

创建索引
> db.t5.ensureIndex({name:1,age:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
查询(没有使用索引)
> db.t5.find({age:{$lt:30}}).explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "server" : "localhost.localdomain:27017",
        "filterSet" : false
}
强制使用索引
> db.t5.find({age:{$lt:30}}).hint({name:1,age:1}).explain()
{
        "cursor" : "BtreeCursor name_1_age_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 37,
        "indexBounds" : {
                "name" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ],
                "age" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ]
        },
        "server" : "localhost.localdomain:27017",
        "filterSet" : false
}

7、删除索引
删除索引分为删除某张表的所有索引 和删除某张表的某个索引,具体如下:

> db.t5.dropIndexes();
{
        "nIndexesWas" : 2,
        "msg" : "non-_id indexes dropped for collection",
        "ok" : 1
}

删除t4表中的firstname索引
> db.t4.dropIndex({firstname:1})
{
        "nIndexesWas" : 2,
        "ok" : 0,
        "errmsg" : "can't find index with key:{ firstname: 1.0 }"
}


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。