瑞_MongoDB_索引-Index

瑞&3l

🙊 前言:本文章为瑞_系列专栏之《MongoDB》的索引-Index篇。由于博主是从B站黑马程序员的《MongoDB》学习其相关知识,所以本系列专栏主要是针对该课程进行笔记总结和拓展,文中的部分原理及图解等也是来源于黑马提供的资料,特此注明。本文仅供大家交流、学习及研究使用,禁止用于商业用途,违者必究!

系列整合篇:《瑞_MongoDB(笔记超详细,有这一篇就够了)》




4 索引-Index

瑞:MongoDB 索引最大的作用在于提升查询效率

4.1 概述

  官网文档:https://docs.mongodb.com/manual/indexes/

  索引支持在 MongoDB 中高效地执行查询。如果没有索引,MongoDB 必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

  如果查询存在适当的索引,MongoDB 可以使用该索引限制必须检查的文档数。

  索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB 还可以使用索引中的排序返回排序结果。

  MongoDB 索引使用 B 树数据结构(确切的说是 B-Tree,MySQL 是 B+Tree)

瑞:B-Tree 可以参考《瑞_数据结构与算法_B树》


4.2 索引的类型

4.2.1 单字段索引

  MongoDB支持在文档的单个字段上创建用户定义的升序 / 降序索引,称为单字段索引(Single Field Index)

  对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引

在这里插入图片描述

4.2.2 复合索引

  MongoDB还支持多个字段的用户定义索引,即复合索引(Compound Index)

  复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由{ userid: 1, score: -1 }组成,则索引首先按userid正序排序,然后在每个userid的值内,再在按score倒序排序。

在这里插入图片描述

4.2.3 其他索引

  地理空间索引(Geospatial Index)、文本索引(Text Indexes)、哈希索引(Hashed Indexes)

  • 地理空间索引(Geospatial Index)

  为了支持对地理空间坐标数据的有效查询,MongoDB 提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。

  • 文本索引(Text Indexes)

  MongoDB 提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”),而将集合中的词作为词干,只存储根词。

  • 哈希索引(Hashed Indexes)

  为了支持基于散列的分片,MongoDB 提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。


4.3 索引的管理操作

  以下示例中的数据准备⬇️

# 创建数据库rayTest
use rayTest

# 创建集合comment并插入数据
db.comment.insertMany([{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}]);

4.3.1 索引的查看

  【说明】返回一个集合中的所有索引的数组

  【语法】

db.collection_name.getIndexes()

提示:该语法命令运行要求是MongoDB 3.0+

  【参数说明】

  • collection_name::集合名称

  【示例】查看comment集合中所有的索引情况

 db.comment.getIndexes()

在这里插入图片描述

  • “v” : 2,表示索引的版本号为2。
  • “key” : {“_id” : 1},表示索引的键值为文档的"_id"字段,值为1表示升序排列。
  • “name” : “_id_”,表示索引的名称为"_id_"。
  • “ns” : “rayTest.comment”,表示该索引属于名为"rayTest"的数据库中的"comment"集合。

  结果中显示的是默认_id索引(此时并没有主动创建过索引)

  默认_id索引:MongoDB 在创建集合的过程中,在_id字段上创建一个唯一的索引,默认名字为_id_,该索引可防止客户端插入两个具有相同值的文档,且不能在_id字段上删除此索引。

  注意:该索引是唯一索引,因此值不能重复,即_id值不能重复的。在分片集群中,通常使用_id作为片键。

4.3.2 索引的创建

  【说明】在集合上创建索引

  【语法】

db.collection_name.createIndex(keys, options)

  【参数说明】

  • collection_name:集合名称
ParameterTypeDescription
keysdocument包含字段和值对的文档,其中字段是索引键,值描述该字段的索引类型。对于字段上的升序索引,请指定值1;对于降序索引,请指定值-1。比如: {字段:1或-1} ,其中1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。另外,MongoDB支持几种不同的索引类型,包括文本、地理空间和哈希索引。
optionsdocument可选。包含一组控制索引创建的选项的文档。有关详细信息,请参见选项详情列表。

options(更多选项)列表⬇️

ParameterTypeDescription
backgroundBoolean建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加"background" 可选参数。 “background” 默认值为false
uniqueBoolean建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
namestring索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDups**Boolean3.0+版本已废弃**。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为false.
sparseBoolean对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSecondsinteger指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
vindex version索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weightsdocument索引权重值,数值在 1 到 99,999之间,表示该索引相对于其他索引字段的得分权重。
default_languagestring对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_overridestring对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为language.

注意:在 3.0.0 版本创建索引方法为db.collection_name.ensureIndex() ,之后的版本使用了 db.collection_name.createIndex()方法,ensureIndex() 还能用,但只是 createIndex() 的别名。

  【示例1】单字段索引示例:对comment集合中userid字段建立索引

db.comment.createIndex({userid:1})

在这里插入图片描述

  【示例2】复合索引:对comment集合中useridnickname同时建立复合(Compound)索引

db.comment.createIndex({userid:1,nickname:-1})

在这里插入图片描述

4.3.3 索引的移除

  【说明】可以移除指定的索引,或移除所有索引

  【语法】

db.collection_name.dropIndex(index)
# 移除集合所有的索引,无参
db.collection_name.dropIndexes()

  【参数说明】

  • collection_name:集合名称
ParameterTypeDescription
indexstring or document指定要删除的索引。可以通过索引名称或索引规范文档指定索引。若要删除文本索引,请指定索引名称。

  【示例1】删除comment集合中userid字段上的升序索引

db.comment.dropIndex({userid:1})

在这里插入图片描述

  【示例2】删除comment集合中名称为userid_1_nickname_-1的复合索引

db.comment.dropIndex("userid_1_nickname_-1")

在这里插入图片描述

  【示例3】删除comment集合中所有的索引

# 先创建一些索引,测试效果用
db.comment.createIndex({userid:1})
db.comment.createIndex({userid:1,nickname:-1})
# 删除`comment`集合中所有的索引
db.comment.dropIndexes()

瑞:默认索引即_id 的字段的索引、名称为_id_的索引是无法删除的,只能删除非_id字段的索引。

在这里插入图片描述


4.4 索引的使用

4.4.1 执行计划

  【说明】

  分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等。

  通常我们想知道建立的索引是否有效,效果如何,都需要通过执行计划查看。

  【语法】

db.collection_name.find(query,options).explain(options)

  【参数说明】

  • collection_name:集合名称
  • explain(options):options有以下几种设置,通常直接使用无参就行
    • queryPlanner:布尔类型,默认为 true。当设置为 false 时,将禁用查询计划,即不会显示查询计划信息。
    • executionStats:布尔类型,默认为 true。当设置为 false 时,不会显示执行统计信息。
    • allPlans:布尔类型,默认为 false。当设置为 true 时,会返回所有候选的查询计划,而不仅仅是胜出的查询计划。
    • allMetrics:布尔类型,默认为 false。当设置为 true 时,会返回所有指标数据。
    • verbosity:字符串类型,可选值为 “queryPlannerAndExecStats”、“queryPlanner”、“executionStats”。这个选项控制输出信息的详细程度。
    • performanceDataTrackingLevel:字符串类型,可选值为
    • level0、level1、level2。这个选项控制性能数据的跟踪级别。
    • maxTimeMS:数字类型,表示查询的最大执行时间(以毫秒为单位)。如果查询超过这个时间限制,将会中断查询并返回当前结果。
    • maxScans:数字类型,表示查询的最大扫描次数。如果查询超过这个扫描次数限制,将会中断查询并返回当前结果。
    • maxIndexes:数字类型,表示查询的最大索引数量。如果查询超过这个索引数量限制,将会中断查询并返回当前结果。

  【示例1】查看comment集合中根据userid查询数据的情况(此时只有默认索引)

db.comment.find({userid:"1003"}).explain()

在这里插入图片描述

  下面对userid建立索引

db.comment.createIndex({userid:1})

  再次查看执行计划

> db.comment.find({userid:"1013"}).explain()
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "rayTest.comment",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "userid" : {
                                "$eq" : "1013"
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "userid" : 1
                                },
                                "indexName" : "userid_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "userid" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "userid" : [
                                                "[\"1013\", \"1013\"]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "localhost.localdomain",
                "port" : 27017,
                "version" : "4.0.10",
                "gitVersion" : "c389e7f69f637f7a1ac3cc9fae843b635f20b766"
        },
        "ok" : 1
}

在这里插入图片描述

4.4.2 涵盖的查询

瑞:类似 MySQL 当中的覆盖索引,不需要回表

  当查询条件和查询的投影仅包含索引字段时,MongoDB 直接从索引返回结果,而不扫描任何文档或将文档带入内存。 这些覆盖的查询可以非常有效。

  【示例】

> db.comment.find({userid:"1003"},{userid:1,_id:0})
{ "userid" : "1003" }
{ "userid" : "1003" }
> db.comment.find({userid:"1003"},{userid:1,_id:0}).explain()
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "rayTest.comment",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "userid" : {
                                "$eq" : "1003"
                        }
                },
                "winningPlan" : {
                        "stage" : "PROJECTION",
                        "transformBy" : {
                                "userid" : 1,
                                "_id" : 0
                        },
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "userid" : 1
                                },
                                "indexName" : "userid_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "userid" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "userid" : [
                                                "[\"1003\", \"1003\"]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "localhost.localdomain",
                "port" : 27017,
                "version" : "4.0.10",
                "gitVersion" : "c389e7f69f637f7a1ac3cc9fae843b635f20b766"
        },
        "ok" : 1
}

在这里插入图片描述




本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为什么会这样[user_mongo@nosql01 replicaset]$ cd /opt [user_mongo@nosql01 opt]$ ll total 0 drwxr-xr-x. 3 root root 25 Mar 16 17:08 servers drwxr-xr-x. 2 root root 51 Mar 16 17:10 software [user_mongo@nosql01 opt]$ tar -zxvf /opt/software/mongodb-linux-x86_64-rhel70-4.4.12.tgz -C /opt/servers/mongodb_demo/replicaset/ mongodb-linux-x86_64-rhel70-4.4.12/LICENSE-Community.txt tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/LICENSE-Community.txt: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/MPL-2 tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/MPL-2: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/README tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/README: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/THIRD-PARTY-NOTICES tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/THIRD-PARTY-NOTICES: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/bin/install_compass tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/bin/install_compass: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/bin/mongo tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/bin/mongo: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/bin/mongod tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/bin/mongod: Cannot open: No such file or directory mongodb-linux-x86_64-rhel70-4.4.12/bin/mongos tar: mongodb-linux-x86_64-rhel70-4.4.12: Cannot mkdir: Permission denied tar: mongodb-linux-x86_64-rhel70-4.4.12/bin/mongos: Cannot open: No such file or directory tar: Exiting with failure status due to previous errors [user_mongo@nosql01 opt]$ tar -zcvf /opt/software/mongodb-linux-x86_64-rhel70-4.4.12.tgz -C /opt/servers/mongodb_demo/replicaset/ tar: Cowardly refusing to create an empty archive Try `tar --help' or `tar --usage' for more information.
06-01

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑞486

你的点赞评论收藏才更是动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值