千家信息网

MongoDB索引概念及使用详解

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,索引,使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构,例如 employee 表的姓名(name)列。如果要按姓查找特定职员,与必须搜索表中的所有行相比,索
千家信息网最后更新 2026年11月01日MongoDB索引概念及使用详解

索引,使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构,例如 employee 表的姓名(name)列。如果要按姓查找特定职员,与必须搜索表中的所有行相比,索引会帮助您更快地获得该信息。


索引的优点:

不需要做全表扫描,只需要扫描索引索引只存储了这个表的数据的一小部分,这小部分可以帮我们实现快速查询,因此扫描的时候只扫描这一小部分即可,如果将这小部分装载入内存中的话,速度会更快

·大大减少了服务器需要扫描的数据量

·索引可以帮助服务器避免排序或使用临时表

·索引可以将随机I/O转换为顺序I/O


索引的缺点:

索引是保存了数据表上的一小部分数据,那么这些数据是需要额外存储的,毫无疑问如果更新了表中的数据,那么响应的索引数据也要跟着更新,加速了查找操作,但是减少了写入速度对查找的加速是否有用还是有待评估的,比如我们将一个表中的按年龄实现了索引创建(在年龄上创建了索引)平时大多数操作都是按照名字上去查找的,那么索引则无任何作用,所谓索引必须跟查找建完全匹配才有意义,但我们要知道大多数的查找未必只在有限字段上执行,也就意味着创建索引必须包含多个段,需要看索引是如何去生成的,对于多个条件可以将索引做为组合索引来查找,所以索引的设计是非常有技巧的

索引本身带来的未必是优势,如果一张表中索引非常的多的话,可能对于整个系统性能的影响是非常大的,如果一张表的本身非常小只有十几行,创建索引反而会减慢速度的,因为全表扫描也未必用不了多长时间

但如果表非常大的话,索引则非常有用,如果数据量过大那么索引反而也未必有意义,比如一张表非常大,上T的数据,可以想象一下创建什么样的索引才可以,所以只能将大表切割成小表,并且分布在不同的物理节点上,对mysql来说叫做分区;对mongodb来讲叫shaerd


索引级别:

索引最高级别3星索引

1星:索引国能将相关的记录放置在一起,大大降低了I/O

2星:索引中数据的存储顺序与查找标准中顺序一致(只要设计良好即可)

3星:如果索引中包含查询中所需要的全部数据(覆盖索引)


索引的类别:

·顺序索引
·散列索引

将索引映射至散列桶中,映射是通过散列函数进行的


评估索引标准:

1、访问类型(如果做等值比较 散列比较好,如果做范围查找,那么顺序比较好

2、访问时长(为完成一个访问,基于索引类型访问的时间可能不同)

3、插入时长(更新表的话索引本身可能会有很大代价,如果散列索引的话只不过重新执行以下算法即可,但是对于顺序索引的话,有可能会移动索引列表后面的索引数据)

4、删除时长

5、空间开销


索引类型:

·顺序索引:按照聚集索引存放的文件也被称为索引顺序文件,最常见的索引类型,一般来讲被索引文件记录,如果按照顺序存放则为索引顺序文件,否则为堆文件

·聚集索引:如果某记录文件中的记录顺序是按照对应的搜索码(键/key)的顺序排序的话,被称为主索引

·非聚集索引:搜索码中的指定的次序与记录中的记录次序不一致


根据索引中是否为每个记录响应的创建索引项:

·稠密索引 (每个搜索码值都有一个对应的索引项

·稀疏索引 (并不是每个记录都有索引项)

·多级索引 (索引指向索引,以此类推,最后的索引指向数据;

索引本身,主索引之外的索引被称为辅助索引,而只有主索引才能使用稀疏索引,其他所有必需是稠密索引,而辅助索引必须是稠密索引

·B+树索引:

·Balance Tree 平衡树索引

·每个叶子节点,从叶子至根的距离是相同的,所以叫做平衡树

·层次需要根据数据量来动态创建层次

·B+树是一种顺序索引



散列索引则:

通过散列函数,数据库加载为一次I/O 指针加载数据为2次 I/O。

I/O是占据时间比例是最大值的,索引散列索引的速度在做精确匹配的时候会更快,因为I/O次数要少的多的多,因此散列索引能够让我们避免访问索引结构的。

散列索引的缺点:散列索引还有可能造成偏斜,长久以来可能发有的散列桶有的满有的空 导致每个节点的负载参差不齐,如果散列函数做的不够随机就有可能造成偏斜的情况

所以散列函数需要做到以下几点:

·分布式随机

·分布式均匀

散列函数适用的场景:精确值匹配,比如做等值比较: = ,IN(), <=> 等


全文索引:

默认情况下顺序索引只能索引字段的前有限个字节,假如字段名是test,test是可以创建存储文本量非常大,不可能将所有的数据全部存放在索引中,肯定只在其中抽取部分字节,所以查找标准肯定是最左前缀方式,不能包含整个字段,如果想实现全文匹配关键字匹配的话,这样则只能使用全文索引(mysql中只有myisam引擎支持)(innodb的话则可以借助外界的索引工具来实现比如sphinx)

如果必须要实现全文索引,使用sphinx是个不错的选择


空间索引:

索引中的数据不能查找,必须使用空间索引函数来获取相应查找结果


索引的特性:

·全值匹配:

简单来讲,匹配他的用户名:Name="User12" ,匹配最左前缀:

Name LIKE"User1%"

无效: Name LIKE"%User1%"


·匹配列前缀:与最左前缀一样(Name LIKE"User1%" 无效: Name LIKE"%User1%") 假如组合索引创建了2个字段:Name,Age 从最左侧开始则有效,那么Age > 80 这样则没有任何意义,因为查找条件一定必须从最左边开始的,但是反过来则非常用有:(Age,Name)

匹配范围值:精确匹配某一列并范围匹配另外一列 比如name=12并age大于80


只访问索引的查询:

假设顺序索引是3级,要找到对应的行数据,如果没有使用覆盖索引,那么需要几次I/O:首先查找到根索引. 然后查找下一级索引,如果下一级索引在磁盘上,那么意味着将装载数据块,这为1次IO ,再一次索引则又消耗一次IO,再次装载硬盘数据,则又一次I/O,如果事先根索引没有被加载,那么至少需要4次I/O才会找到数据

主键,唯一键 都是顺序索引,但是唯一不同的地方是:主键是不能重复 不能为空,唯一键可以重复可以为空


创建索引:

> db.testcoll.find()

{ "_id" : ObjectId("531fbe8d020f14309ee1410a"), "Name" : "User1","Age" : 1, "Gender" : "M", "preferbook": [ "blue book", "yellow book" ] }
{ "_id" : ObjectId("531fbe8d020f14309ee1410b"), "Name" : "User2","Age" : 2, "Gender" : "M", "preferbook": [ "blue book", "yellow book" ] }
{ "_id" : ObjectId("531fbe8d020f14309ee1410c"), "Name" : "User3","Age" : 3, "Gender" : "M", "preferbook": [ "blue book", "yellow book" ] }

如上所示,我们要在用户字段名上创建索引,注意的是字段id默认就是索引,而且是主键索引,我们在主键索引之外创建索引都被称为辅助索引 ,因为表内大多数都是根据用户名来查找的,所以希望根据用户名来查找索引:


使用命令ensureIndex 在Name字段上创建索引

> db.testcoll.ensureIndex({Name:1})

查看索引:

> db.testcoll.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" :"testdb.testcoll",
"name" :"_id_"
},

#第二个索引是在name上创建,是我们自己指定的,如下所示:

{
"v" : 1,
"key" : {
"Name" : 1
},
"ns" :"testdb.testcoll",
"name" :"Name_1"
}

删除索引:

可以使用dropIndex 将name字段的索引删除

> db.testcoll.dropIndex({Name:1})
{ "nIndexesWas" : 2, "ok" : 1 }

再次查看其索引

> db.testcoll.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" :"testdb.testcoll",
"name" :"_id_"
}
]

删除coll所有的索引

> db.testcoll.dropIndex({Name:1})


同时也支持使用唯一索引,我们可以在name这个字段上创建唯一索引,也就意味着用户名不得出现重复的名字

#唯一索引

> db.testcoll.ensureIndex({Name:1},{unique:true})

#稀疏索引

> db.testcoll.ensureIndex({Name:1},{sparse:true})


MongoDB中所支持的索引类型

对mongodb来讲,索引可以创建在collection级别,也可以创建在sub-field中()子collection

完全可以根据自己的需求创建,那么索引可以将随机IO转换为顺序IO

索引类型:

1、单键索引(创建在一个字段上的索引)

2、组合索引(上面提到了)

3、多键索引(一个文档中某个字段的值可以是数组,如果创建在这么个字段上,一个字段上有多个值,则为多键索引,(一个值为一个数组))

4、空间索引(只能使用空间索引函数,与mysql一致)

5、文本索引(全文索引)

6、哈希索引


创建哈希索引的话,必须明确说明哈希的格式才可以,如下所示:

>db.testcoll.ensureIndex({Name:"hashed"})

> db.testcoll.dropIndex({Name:"hashed"})


显示索引是否能用到:

显示查询语句是否能真正用到所创建的索引:

> db.testcoll.find({Name: "User19"}).explain()
{
"cursor" : "BtreeCursor Name_1",
"isMultiKey" : false, #
是否用到键
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1, #扫描了多少个记录
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false, #扫描后有没有记录
"indexOnly" : false, #是否用到索引,是否仅在索引中
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"Name" : [
[
"User19",
"User19"
]
]
},
"server" : "localhost:27017"
}


将索引删除:

> db.testcoll.find({Name: "User19"}).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 99, #
扫描的对象为全部,意为全表扫描
"nscanned" : 99,
"nscannedObjectsAllPlans" : 99,
"nscannedAllPlans" : 99,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {

},
"server" : "localhost:27017"
}

在查询的时候可以用hint指定使用的索引

> db.testcoll.find({Name: "User19"}).hint({Name:1}).explain()


创建组合索引

> db.testcoll.ensureIndex({Name:1,Age:1},{uniqe:true})

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

如果不指定则在name:1上查找索引。如下所示:

> db.testcoll.find({Name: "User19"}).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" : 0,
"indexBounds" : {
"Name" : [
[
"User19",
"User19"
]
],
"Age" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "localhost:27017"
}



索引 数据 顺序 字段 函数 列索 文件 类型 部分 全文 用户 空间 查询 前缀 用户名 速度 存储 搜索 组合 不同 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技互联网政务服务 北京互联网科技有限公司 互联网金融公司科技 有木互联网科技 互联网科技公司名称 佰商互联网科技有限公司 顶级互联网科技成果有哪些 阿里互联网科技公司 宁夏科技产业互联网案例 佛山市翊博互联网络科技有限公司 四川慕妮娅互联网科技有限公司 明优互联网科技有限公司 互联网科技公司营业执照怎么办理 互联网营销推广黑科技 西安有哪些互联网高科技企业 广西科技产业互联网是什么 众联互联网络科技 恒生科技指数 中概互联网 互联网金融金融科技 北京品多多互联网科技有限公司 科技和互联网公司 北京互联网科技公司 互联网科技金融公司 卓越科技(互联网 ) 互联网科技公司名称 佰商互联网科技有限公司 无锡溥仪互联网科技有限公司 农村开互联网科技讲堂 杭州壁岐互联网科技有限公司 互联网 科技节活动 微视频大赛
0