0

0

玩转mongoDB(六):索引,速度的引领(普通索引篇)

爱谁谁

爱谁谁

发布时间:2025-07-16 09:18:45

|

816人浏览过

|

来源于php中文网

原创

数据库索引的概念类似于书籍的索引,拥有索引后无需翻阅整本书,数据库可以直接在索引中进行查找,找到条目后即可跳转到目标文档的位置,这可以显著提高查询速度,通常是几个数量级的提升。

一、创建索引

在person集合的age字段上创建索引,并比较创建索引前后查询语句的性能差异。

创建索引的命令为:db.person.ensureIndex({"age":1})。这里我们使用了ensureIndex在age字段上建立索引。值为“1”表示按照age进行升序排列,而“-1”表示按照age进行降序排列。

没有索引时的查询性能:

玩转mongoDB(六):索引,速度的引领(普通索引篇)

有索引时的查询性能:

玩转mongoDB(六):索引,速度的引领(普通索引篇)

我们主要关注几个关键参数(参数说明请参考上一篇文章):

  • executionTimeMillis(这次查询的总耗时):无索引时耗时962毫秒;有索引时耗时143毫秒。
  • totalDocsExamined(文档扫描条目):无索引时为200万条;有索引时为2000条。
  • stage(查询的类型):无索引时为COLLSCAN(全表扫描);有索引时为FETCH+IXSCAN(索引扫描+根据索引检索指定文档)。
  • executionStages.executionTimeMillisEstimate(检索文档获得数据的耗时):无索引时耗时910毫秒;有索引时耗时0毫秒。

建立索引后,该查询的整体速度提高了一个数量级(1个数量级即10倍)。根据查询语句的不同,索引可以使速度提高几个数量级。

二、复合索引

在多个字段上建立的索引称为复合索引。有时我们的查询不是单条件的,可能是多条件的,例如查找年龄在20至30岁之间且名字为‘ryan1’的同学,我们可以建立“age”和“name”的联合索引来加速查询。

为了演示索引的效果,我们重新生成并插入200万个文档的集合。

我们可以使用hint()方法来强制查询使用特定索引。

来看一下,当查询条件是多个时,复合索引相比单键索引的优势。

使用单键索引:

db.person.find({"age":{"$gte":20,"$lte":30},"name":"ryan1"}).hint({"age":1}).explain("executionStats");

结果如下:

Heeyo
Heeyo

Heeyo:AI儿童启蒙陪伴师,风靡于硅谷的儿童AI导师和玩伴

下载
{    ...    "executionStats" : {        "executionSuccess" : true,        "nReturned" : 2000,        "executionTimeMillis" : 2031,        "totalKeysExamined" : 2000000,        "totalDocsExamined" : 2000000,    ...    }

使用复合索引:

db.person.find({"age":{"$gte":20,"$lte":30},"name":"ryan1"}).hint({"age":1,"name":1}).explain("executionStats");

结果如下:

{    ...    "executionStats" : {        "executionSuccess" : true,        "nReturned" : 2000,        "executionTimeMillis" : 8,        "totalKeysExamined" : 2010,        "totalDocsExamined" : 2000,    ...}

从executionTimeMillis的值上可以看出区别。单键索引耗费了2031毫秒,而复合索引仅用了8毫秒。因此,对于多条件的查询语句,建立正确的复合索引是非常重要的。

下面我们再介绍一种复合索引的重要应用场景:对一个字段排序并只获取前100个结果(实际项目中常见这种情况)。对于这种情况,索引应该这样建立{"sortKey":1,"queryCriteria":1},排序的字段应放在复合索引的第一位。

排序字段未放在复合索引的第一位:

db.person.find({"age":{"$gte":21.0,"$lte":30.0}}).sort({"name":1}).limit(100).hint({"age":1,"name":1}).explain("executionStats");

结果如下:

{    ...        "executionStats" : {        "executionSuccess" : true,        "nReturned" : 100,        "executionTimeMillis" : 6882,        "totalKeysExamined" : 1800000,        "totalDocsExamined" : 1800000,    ...  }

排序字段放在复合索引的第一位:

db.person.find({"age":{"$gte":21.0,"$lte":30.0}}).sort({"name":1}).limit(100).hint({"name":1,"age":1}).explain("executionStats");

结果如下:

{    ...    "executionStats" : {        "executionSuccess" : true,        "nReturned" : 100,        "executionTimeMillis" : 3,        "totalKeysExamined" : 2100,        "totalDocsExamined" : 2100,    ...}

从上面的结果可以看出,基于排序字段的索引效果非常好。

分析:第一种索引,需要找到所有符合复合查询条件的值(依据索引,字段和文档可以快速找到),但找到后,需要在内存中对文档进行排序,这个步骤消耗了大量时间。第二种索引效果非常好,因为无需在内存中对大量数据进行排序。然而,MongoDB仍需扫描整个索引以找到所有文档。因此,如果对查询结果的范围进行了限制,那么MongoDB在几次匹配后就可以停止扫描索引,在这种情况下,将排序字段放在第一位是一个非常好的策略。

三、唯一索引

唯一索引可以确保集合中每个文档的指定字段具有唯一值。如果想保证不同文档的“name”字段值不同,可以在“name”字段上创建唯一索引。

db.person.ensureIndex({"name":1},{"unique":true});

然后使用db.person.getIndexes()命令查看目前person集合的所有索引。

玩转mongoDB(六):索引,速度的引领(普通索引篇)

也可以创建复合的唯一索引。创建复合唯一索引时,单个字段的值可以相同,但所有字段的组合值必须是唯一的。

db.person.ensureIndex({"name":1,"age":1},{"unique":true}); 

然后使用db.person.getIndexes()命令查看目前person集合的所有索引。

玩转mongoDB(六):索引,速度的引领(普通索引篇)

四、稀疏索引

唯一索引会将null视为值,因此无法将多个缺少唯一索引中字段的文档插入到集合中。然而,在某些情况下,你可能希望唯一索引只对包含相应字段的文档生效。这时可以使用MongoDB中的稀疏索引。该索引与关系型数据库中的稀疏索引完全不同。MongoDB中的稀疏索引只是不需要将每个文档都作为索引条目。

例如,如果有一个可选的mobilephone字段,但如果提供了该字段,其值必须是唯一的:

db.person.ensureIndex({"mobilephone":1},{"unique":true,"sparse":true});

稀疏索引不必是唯一的。只要去掉unique选项,就可以创建一个非唯一的稀疏索引。

玩转mongoDB(六):索引,速度的引领(普通索引篇)

五、索引管理

如第一小节所述,可以使用ensureIndex方法创建新的索引,也可以使用createIndex方法。

创建索引后,可以使用getIndexes()方法查看给定集合上的所有索引信息。

db.person.getIndexes();//获取集合的索引信息

结果如下:

[    {        "v" : 1,        "key" : {            "_id" : 1        },        "name" : "_id_",        "ns" : "personmap.person"    },    {        "v" : 1,        "unique" : true,        "key" : {            "name" : 1.0        },        "name" : "name_1",        "ns" : "personmap.person"    },    {        "v" : 1,        "unique" : true,        "key" : {            "name" : 1.0,            "age" : 1.0        },        "name" : "name_1_age_1",        "ns" : "personmap.person"    },    {        "v" : 1,        "unique" : true,        "key" : {            "mobilephone" : 1.0        },        "name" : "mobilephone_1",        "ns" : "personmap.person",        "sparse" : true    }]

随着业务的不断变化,你可能会发现数据或查询已经发生了改变,原来的索引可能不再那么有效。这时可以使用dropIndex()方法删除不需要的索引:

db.person.dropIndex("name_1");//删除索引名为name_1的索引。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

231

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

436

2024.03.01

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

281

2023.07.18

mongodb启动命令
mongodb启动命令

MongoDB 是一种开源的、基于文档的 NoSQL 数据库管理系统。本专题提供mongodb启动命令的文章,希望可以帮到大家。

250

2023.08.08

MongoDB删除数据的方法
MongoDB删除数据的方法

MongoDB删除数据的方法有删除集合中的文档、删除整个集合、删除数据库和删除指定字段等。本专题为大家提供MongoDB相关的文章、下载、课程内容,供大家免费下载体验。

160

2023.09.19

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

972

2023.11.02

mongodb有哪些应用领域
mongodb有哪些应用领域

mongodb 的应用领域涵盖广泛,包括内容管理系统、社交媒体、分析、移动应用、物联网、金融科技、医疗保健和广告技术等领域,因其灵活性、可扩展性和易用性而广受欢迎。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

336

2024.04.02

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

479

2024.04.02

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MongoDB 教程
MongoDB 教程

共17课时 | 2.2万人学习

黑马云课堂mongodb实操视频教程
黑马云课堂mongodb实操视频教程

共11课时 | 3.1万人学习

MongoDB 教程
MongoDB 教程

共42课时 | 25.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号