Java

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonD

2019-08-04  本文已影响3人  勤奋的码农
浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

前言

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中( 索引存储在特定字段或字段集的值),而且是使用了B-tree结构。索引可以极大程度提升MongoDB查询效率。

如果没有索引,MongoDB必须执行全集合collections扫描,即扫描集合中的每个文档,选取符合查询条件的文档document。 如果查询时存在适当的索引,MongoDB可以使用索引来限制它必须查询的文档document的数量,特别是在处理大量数据时,所以选择正确的索引是很关键的、重要的。Java交流学习交流圈子

创建索引,需要考虑的问题:

索引限制:

1. 索引管理

1.1 索引创建

索引创建使用createIndex()方法,格式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

createIndex() 接收可选参数,可选参数列表如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题 浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.2 查看索引

查看Collection中所有索引,格式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.3 删除索引

删除Collection中的索引:格式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.4 索引名称

索引的默认名称是索引键和索引中每个键的value1或-1,形式index_name+1/-1,比如:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

也可以指定索引名称:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.5 查看索引创建过程以及终止索引创建

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.6 索引使用情况

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.7 MongoDB度量标准

MongoDB提供了许多索引使用和操作的度量标准,在分析数据库的索引使用时可能需要考虑这些度量标准,如下所示:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

1.8 后台索引操作

在密集(快达到数据库最大容量)Collection创建索引:在默认情况下,在密集的Collection(快达到数据库最大容量)时创建索引,会阻止其他操作。在给密集的Collection(快达到数据库最大容量)创建索引时, 索引构建完成之前,保存Collection的数据库不可用于读取或写入操作。 任何需要对所有数据库(例如listDatabases)进行读或写锁定的操作都将等待不是后台进程的索引构建完成。

因此可以使用background属性进行设置后台索引创建,操作如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

2. 索引类型

2.1 单字段索引(Single Field Indexes)

MongoDB可以在任何一个字段中创建索引,默认情况下,所有的集合(collections)会在_id字段中创建索引。_id索引是为防止客户端插入具有相同value的_id字段的文档Document,而且不能删除_id字段索引。

在分片群集中使用_id索引,如果不使用_id字段作为分片键,则应用程序必须确保_id字段中值的唯一性以防止出错,解决方法为使用标准的自动生成的ObjectId来完成。

一般单字段索引的value中,“1”指定按升序对项目进行排序的索引,“-1”指定按降序对项目进行排序的索引。如下所示:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

在单个字段创建索引,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

在嵌入式文档Document中的字段创建索引,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

在嵌入式文档Document创建索引,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

2.2 复合索引(Compound Index)

复合索引指的是将多个key组合到一起创建索引,这样可以加速匹配多个键的查询。特性如下:

创建复合索引的格式:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

排序顺序,两个字段的复合索引示例,index{userid:1,score:-1},先userid的value排序,然后再userid排序基础下进行score排序。如下图:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题 浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

创建复合索引,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

复合索引中的前缀查询,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

2.3 多键索引

MongoDB使用多键索引为数组的每个元素都创建索引,多键索引可以建立在字符串、数字等key或者内嵌文档(document)的数组上,如果索引字段包含数组值,MongoDB会自动确定是否创建多键索引; 您不需要手动指定多键类型。 其中创建方式:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

索引边界

使用多键索引,会出现索引边界(索引边界即是查询过程中索引能查找的范围)的计算,并计算必须遵循一些规则。即当多个查询的条件中字段都存在索引中时,MongoDB将会使用交集或者并集等来判断这些条件索引字段的边界最终产生一个最小的查找范围。可以分情况:

1).交集边界

交集边界即为多个边界的逻辑交集,对于给定的数组字段,假定一个查询使用了数组的多个条件字段并且可以使用多键索引。如果使用了$elemMatch连接了条件字段,则MongoDB将会相交多键索引边界,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

查询条件分别为大于等于3、小于等于6,其中 (1)中使用了elemMatch连接查询条件,会产生一个交集ratings:[[3,6]。在(2)查询中,没使用elemMatch,则不会产生交集,只要满足任何一个条件即可。

2).并集边界

并集边界常常用在确定多键组合索引的边界,例如:给定的组合索引{a:1,b:1},在字段a上有一个边界:[3,+∞),在字段b上有一个边界:(-∞,6],相并这两个边界的结果是:{ a: [ [ 3, Infinity ] ], b: [ [ -Infinity, 6 ] ] }。

而且如果MongoDB没法并集这两个边界,MongoDB将会强制使用索引的第一个字段的边界来进行索引扫描,在这种情况下就是: a: [ [ 3, Infinity ] ]。

3)、数组字段的组合索引

一个组合索引的索引字段是数组,例如一个survey collection集合document文档中含有item字段和ratings数组字段,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

分别处理查询条件:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

MongoDB使用并集边界来组合这两个边界:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

4).内嵌文档document的数组上建立组合索引

如果数组中包含内嵌文档document,想在包含的内嵌文档document字段上建立索引,需要在索引声明中使用逗号“,” 来分隔字段名,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

则score字段名称就是:ratings.score。

5).混合不是数组类型的字段和数组类型字段的并集

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

分别对查询条件进行处理:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

MongoDB可以组合 item键的边界与 ratings.score和ratings.by两个边界中的一个,到底是score还是by索引边界这取决于查询条件和索引键的值。MongoDB不能确保哪个边界和item字段进行并集。 但如果想组合ratings.score和ratings.by边界,则查询必须使用$elemMatch。Java交流学习交流圈子

6).数组字段索引的并集边界

在数组内部并集索引键的边界,

比如:在ratings.score和ratings.by字段上创建组合索引:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

字段ratings.score和ratings.by拥有共同的路径ratings。下面的查询使用$elemMatch则要求ratings字段必须包含一个元素匹配这两个条件:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

分别对查询条件进行处理:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

MongoDB可以使用并集边界来组合这两个边界:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

7). 还有不使用elemMatch进行查询以及不完整的路径上使用elemMatch,想要了解更多可以查看《官方文档-Multikey Index Bounds》。

限制:

2.4 全文索引(text index)

MongoDB提供了一种全文索引类型,支持在Collection中搜索字符串内容,对字符串与字符串数组创建全文可搜索的索引 。 这些全文索引不存储特定于语言的停用词(例如“the”,“a”,“或”),并且阻止document集合中的单词仅存储根词。创建方式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

而且MongoDB提供权重以及通配符的创建方式。查询方式多个字符串空格隔开,排除查询使用“-”如下所示:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

要删除全本索引,需要将索引的名称传递给db.collection.dropIndex()方法, 而要获取索引的名称,使用db.collection.getIndexes()方法。

还可以指定全文索引的语言,通过default_language属性 在创建时指定, 或者使用language_override属性 覆盖掉创建document文档时默认的语言,如下所示:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

权重

每个全文索引可以通过设置权重来分配不同的搜索程度,默认权重为1,对于文档中的每个索引字段,MongoDB将匹配数乘以权重并将结果相加。 使用此总和,MongoDB然后计算文档的分数,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

content权重为10,keywords为5,about为默认权重1,因此可以得出content对于keywords查询频率高于2倍,而对于about字段则是10倍。

通配符全文索引

在多个字段上创建全文索引时,还可以使用通配符说明符($**)。 使用通配符全文索引,MongoDB会为包含Collection中每个Document的字符串数据。例如:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

通配符全本索引是多个字段上的全本索引。 因此,可以在创建索引期间为特定字段指定权重,以控制结果的排名。

限制

2.5 Hash 索引

散列索引使用散列函数来计算索引字段值的散列值。 散列函数会折叠嵌入的文档并计算整个值的散列值,但不支持多键(即数组)索引。 生成hash索引key使用了convertShardKeyToHashed()方法。创建方式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

而且散列索引支持使用散列分片键进行分片。 基于散列的分片使用字段的散列索引作为分片键来分割整个分片群集中的数据。

3. 索引属性

索引属性有TTL索引、惟一性索引、部分索引、稀疏索引以及区分大小写索引。

3.1 TTL索引(TTL Indexes)

TTL索引是特殊的单字段索引,并且字段类型必须是date类型或者包含有date类型的数组,MongoDB可以使用它在一定时间后或在特定时钟时间自动从集合中删除文档。 数据到期对于某些类型的信息非常有用,例如机器生成的事件数据,日志和会话信息,这些信息只需要在数据库中持续有限的时间。Java交流学习交流圈子

创建TTL索引方法,和普通索引的创建方法一样,只是会多加一个expireAfterSeconds的属性,格式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

例子:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

指定过期时间

首先在保存BSON日期类型值或BSON日期类型对象数组的字段上创建TTL索引,并指定expireAfterSeconds值为0.对于集合中的每个文档,设置 索引日期字段为与文档到期时间对应的值。示例操作如下:

第一步:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

第二步:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

数据过期类型:

TTL索引特有限制:

3.2 惟一性索引(Unique Indexes)

唯一索引可确保索引字段不存储重复值; 即强制索引字段的唯一性。 默认情况下,MongoDB在创建集合期间在_id字段上创建唯一索引。创建方式如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

单个字段创建方式,示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

唯一性复合索引: 还可以对复合索引强制执行唯一约束。 如果对复合索引使用唯一约束,则MongoDB将对索引键值的组合强制实施唯一性。示例如下

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

唯一多键索引:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

创建唯一索引到副本或者分片中: 对于副本集和分片集群,使用滚动过程创建唯一索引需要在过程中停止对集合的所有写入。 如果在过程中无法停止对集合的所有写入,请不要使用滚动过程。 相反,通过以下方式在集合上构建唯一索引:

NOTE:详细解析可以看

限制:

3.3 部分索引(Partial Indexes)

部分索引通过指定的过滤表达式去达到局部搜索。通过db.collection.createIndex()方法中增加partialFilterExpression属性创建,过滤表达式如下:

示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

其中:

限制:

3.4 稀疏索引(Sparse Indexes)

稀疏索只引搜索包含有索引字段的文档的条目,跳过索引键不存在的文档,即稀疏索引不会搜索不包含稀疏索引的文档。默认情况下, 2dsphere (version 2), 2d, geoHaystack, 全文索引等总是稀疏索引。创建方式db.collection.createIndex()方法增加sparse属性,如下所示:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

稀疏索引不被使用的情况: 如果稀疏索引会导致查询和排序操作的结果集不完整,MongoDB将不会使用该索引,除非hint()示显式指定索引。

稀疏复合索引:

稀疏索引与唯一性: 一个既包含稀疏又包含唯一的索引避免集合上存在一些重复值得文档,但是允许多个文档忽略该键。满足稀疏索引和唯一性操作其两个限制都要遵循。

整合示例如下:

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

其中:

4. 其他事项

4.1 索引策略

索引策略:

粉丝福利

浅入浅出MongonDB,教你轻松应对面试中遇到的MongonDB索引问题

推荐一个Java交流学习交流圈子 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

上一篇 下一篇

猜你喜欢

热点阅读