MongoDB索引机制详解
目录
- ? MongoDB 的索引机制
- ? 索引的类型
- ?? 创建索引 - 单字段索引
- ?? 创建索引 - 多字段索引
- ?? 创建索引 - 唯一性索引
- ?? 创建索引 - 文本索引
- ?? 创建索引 - 地理空间索引
- ? 查看所有索引
- ? 删除索引
- ? MongoDB 索引使用原则
? MongoDB 的索引机制
与MySQL 一样,"索引" 在 MongoDB 中也是用于优化查询的一种数据结构。
通过创建适当的索引,MongoDB 能够快速地定位符合查询条件的文档,从而减少了扫描文档的数量,提高了查询性能。
? 索引的类型
MongoDB 的索引也是为了提升数据的检索速度,原理也是先对数据进行排序,然后就可以提升检索的速度了。
因为是 NoSQL 数据库,所以 MongoDB 存放记录的数量要远超 MySQL ,如果没有索引,一个查询请求就会让 MOngoDB 做全表扫描,这种检索效率是非常低的。
一次查询要花费几十秒甚至几分钟的时间,所以 “索引机制” 对于在海量数据中的快速定位查找就非常的重要了。
常用的索引有 "单字段索引"、"多字段索引"、"文本索引"、"空间索引" 等,接下来我们就来一一了解吧。
?? 创建索引 - 单字段索引
单字段索引是最简单的索引类型,它只包含一个字段。以前面章节中我们使用到的 “student” 集合 为例,可以在 name 字段上创建一个单字段索引。
单字段索引的创建语法:db.collection.createIndex({key:1},options);
- collection 为某一个集合;
- createIndex 为创建索引的函数;
- key 为需要创建索引的字段, 1 表示升序排序,如果想要按照降序排序,可以使用 -1;索引可以加速对 key 字段的查询。
示例如下:
db.student.createIndex({name: 1 }); // 为集合 student 中 name 字段 创建索引,升序排列。
在创建索引的时候,经常会使用的一些选项参数,比如为索引命名、利用非阻塞模式等等,尤其是 “非阻塞模式”。在下文中的 “索引时的一些重要选项参数” 有详细介绍。
?? 创建索引 - 多字段索引
多字段索引包含多个字段,用于加速涉及多个字段的查询。
例如,在 students 集合中同时对 "name" 和 "age" 字段创建一个多字段索引
:db.student.createIndex({name:1, age:-1}); // 为集合 student 中 name 字段 创建索引,升序排列, age 字段也创建索引,降序排列
上述代码创建了一个名为
name_1_age_-1的多字段索引,其中的
1和
-1分别表示
name字段和
age 字段的排序规则。
?? 创建索引 - 唯一性索引
"唯一性索引" 用于确保一个集合中的文档在指定字段上的值是唯一的。
唯一性索引只能创建在每个记录都含有的公共字段上,在非公共字段上是不能创建唯一-性索引的。
在创建 “唯一性索引” 之后,MongoDB 会在索引中记录每个文档在该字段上的值,在插入或更新文档时,MongoDB 会比对索引中的值;
如果发现该字段上已经存在同样的值,就会拒绝写入操作并抛出一个错误。
在创建 “唯一性索引” 的时候,需要传入 "unique 参数" 用于指定索引是否唯一。如果设置为 true,则在创建时将强制执行该索引的唯一性约束。
以下是一个创建唯一索引的示例:
db.student.createIndex({"tel": 1},{ unique: true}); // 将集合 "student" 中 tel 字段设置为唯一索引
上述代码将在 student 集合的 tel 字段上创建一个唯一性索引。在该索引中,每个文档都对应一个唯一的 tel 值。
需要注意的是,唯一性索引可能会影响 MongoDB 的性能,因为 MongoDB 需要在每个写入操作中比较正在写入的文档与索引中的值。因此,在创建唯一性索引时,需要根据需要选择合适的字段,并避免过多的唯一性索引。
同时,在操作唯一性索引时,需要注意相关异常处理,例如捕获索引操作抛出的错误,以及避免在异常处理之前对集合进行其他的写入操作。
?? 创建索引 - 文本索引
文本索引也叫做全文索引,一般用于支持全文搜索。
通过在某些字段上创建文本索引,MongoDB 可以加速全文搜索操作,例如搜索文章中的一些关键字。
以下是一个使用文本索引实现全文搜索的示例:
db.articles.createIndex({content:"text"}); db.articles.find({$text:{ $search: "MongoDB is awesome"}});
上述代码对
articles
集合的 content
字段创建了一个文本索引,用于支持全文搜索。查询语句中,使用
$text
操作符指定使用全文索引,并传递了需要搜索的关键字 "MongoDB is awesome"
。?? 创建索引 - 地理空间索引
了解即可,反正我是没用过。
在 MongoDB 中,地理空间索引用于支持地理位置(如经度和纬度)的搜索和查询。通过创建地理空间索引,MongoDB 可以快速地定位符合特定地理范围内的文档。
在 MongoDB 中,有两种类型的地理空间索引:2d 索引和2dsphere 索引。其中,2d 索引适用于操作平面上的地理位置信息,例如某个城市中的商铺,而2dsphere 索引适用于操作三维空间中的地理位置信息,例如地球上的各个地理位置。
以下是一个在
stores
集合上创建 2dsphere 索引的示例:(示例是网上搜的)db.stores.createIndex({ location: "2dsphere" });
上述代码在
stores
集合的 location
字段上创建了一个 2dsphere 索引,以支持地理位置搜索。下面是一个基于该索引的查询示例:
db.stores.find({ location: { $near: { $geometry: { type: "Point", coordinates: [ -73.97, 40.77 ] }, $maxDistance: 5000 } } });
在上述示例中,使用 $near 操作符和 $geometry 选项来定义将要搜索的坐标点 [ -73.97, 40.77 ],并使用 $maxDistance 选项来设置搜索的最大半径为 5000 米。MongoDB 会使用 2dsphere 索引来快速地找到在这个范围内的文档。
需要注意的是,在使用地理空间索引时,需要注意索引的创建和使用方式,以及数据类型的正确性。同时,也需要注意地理空间索引可能会带来的性能开销,并根据具体需求进行索引的优化和调整。
? 查看所有索引
当我们创建了索引之后,可以通过 getIndexes() 函数可以获取集合中所有索引。
查看索引语法示例:
db.student.getIndexes() // 查看集合 student 中的所有 "索引"
? 删除索引
在 MongoDB 中,我们可以使用 dropIndex() 函数来删除一个指定的索引,也可以使用 dropIndexes() 删除一个集合上的所有索引。
**dropIndex() 函数 ** 需要指定要删除索引的集合名称和索引的名称或者参数。
例如,下面的代码演示如何删除名为 name_1 的索引:
db.student.dropIndex("name_1");
除了提供索引的名称以外,还可以通过提供一个索引键或一个描述索引的选项对象来删除特定的索引。
以下示例演示如何基于索引键删除索引:
db.student.dropIndex({name_1: 1 });
在上述示例中,我们通过对象字面量传递一个索引键
{ email: 1 }
,MongoDB 将会删除关联到该键的索引。我们还可以使用 dropIndexes() 函数 来删除一个集合上的所有索引。
以下是删除所有索引的示例:
db.student.dropIndexes();
删除索引之前需要确保是否真的需要删除,因为索引是用于加速查询的。同时,还需要注意删除索引所带来的可能的性能问题。
如果删除的索引是频繁使用的索引,那么从索引中读取文档的性能会降低,因为 MongoDB 会像查询数据库时一样执行全文检索。
所以,在删除索引之前,需要对索引的使用情况做充分的评估。
? MongoDB 索引使用原则
MongoDB 索引的使用原则与 MySQL 是一致的:
- 数据量很大的集合必须创建索引,相反则不需要使用索引。
- 如果集合的数据读取多过写入,也是需要创建索引的,因为索引提升的事查询的速度;如果数据的写入多过了数据的读取,设置索引提升不了写入的速度,反而会拖慢写入的速度。因为写入新的数据或者修改数据都会引发数据的排序,因此就会影响到写入的速度。
- 并不是索引越多越好,那些经常被用来当做检索条件的字段应该设置索引,没有被经常当做检索条件的字段不需要设置索引。