首页 > 数据库 >MongoDB09-索引

MongoDB09-索引

时间:2022-09-20 01:00:53浏览次数:85  
标签:创建 db 索引 字段 文档 id MongoDB09

  • MongoDB的索引用于查询(find、findOne)和排序。
    • 如果倾向于在集合中大量使用排序,那么应该根据排序的需求添加索引。如果在一个没有索引的集合中对目标字段使用sort(),并且数据量超过内部排序缓冲的最大大小,就会看到错误消息。
  • 在集合中添加索引后,MongoDB必须维护它们,并在每次执行写操作(例如更新、插入,或删除)时对它们进行更新。如果在集合中有过多的索引,它们有可能会对写操作的性能造成负面影响。
  • 索引最好用在读操作多的集合中。写入频繁的集合(例如日志系统),引入索引可能会减少每秒写入的文档数量峰值(这些文档可能会大量涌入集合中)。
  • 每个集合中最多有64个索引。

1、查看索引

  • getIndexes函数会显示指定集合中的索引。显示所有索引,包括它们引用的字段或元素,以及在索引上设置的任何选项。
  • getIndexes函数的基本语法格式如下:
db.collection.getIndexes()
  • 当在某个元素上定义索引时,MongoDB将构造一个二叉树索引,并用它高效地定位文档。如果未找到合适的索引,MongoDB将扫描集合中的所有文档,搜索满足查询的记录。

示例:

  • people集合没有任何用户自定义的索引,但MongoDB自动为这个集合的_id字段创建了索引。不需要做任何操作来创建或删除_id_索引,MongoDB将在集合创建时创建该索引,在集合删除时删除该索引。
> db.people.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

2、创建索引

  • createIndex函数的基本语法格式如下:
    • 首先将检查目前集合中是否已经创建了该索引。如果是,那么createlndex()只是返回该索引。
//在集合上创建索引
db.collection.createIndex(keys, options, commitQuorum)

//在集合上创建一个或多个索引
db.collection.createIndexes( [ keyPatterns ], options, commitQuorum )
  • createIndex函数的参数:
    • keys:包含字段和值的文档,其中字段是索引键,值是该字段的索引类型。对于字段的升序索引值是1; 对于降序索引,值是-1。从3.6开始,不能指定*为索引名称。
    • options:可选的。包含一组控制创建索引的选项的文档
    • commitQuorum:可选的。提交法定人数
  • options可用参数有:
//可用于所有索引类型的option
background: boolean,可选的。在MongoDB 4.2中已弃用。"background: true"指示MongoDB在后台构建索引。默认值为false。
unique:	boolean,可选的。是否创建唯一索引。若为true,则创建唯一索引。默认值为false。
name: string,可选的。索引的名称。如果未指定,MongoDB通过连接索引字段的名称和排序顺序来生成索引名。
partialFilterExpression: document,可选的。如果指定,索引只引用匹配筛选器表达式的文档。
sparse: boolean,可选的。如果为true,则索引只引用具有指定字段的文档。默认值为false。
expireAfterSeconds: integer,可选的。指定一个值(以秒为单位)作为TTL,以控制MongoDB在这个集合中保留文档的时间。
hidden: boolean,可选的。用于确定是否对查询计划器隐藏索引。
storageEngine: document,可选的。在创建索引时指定存储引擎。
//可用于排序的option
collation: {               //可选的。指定索引的排序规则。
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}
//文本(text)索引选项
weights: document,可选的。对于文本索引,是包含字段和权重对的文档。权重是1到99,999之间的整数,表示该字段相对于其他索引字段的重要性。可以为部分或所有索引字段指定权重。参见使用权重控制搜索结果来调整分数。缺省值为1。
default_language: string,可选的。对于文本索引,确定停止词列表以及词干分析器和标记分析器的规则的语言。
language_override: string,可选的。对于文本索引,是集合文档中包含文档的覆盖语言的字段的名称。默认值为language。
textIndexVersion: integer,可选的。文本索引版本号。用户可以使用此选项覆盖默认版本号。

2.1、创建简单索引

  • 使用嵌入式文档中的字段,可使用普通的点标记寻址模式。
  • 如果指定的文档字段是数组类型,那么该索引将把数组中的所有元素作为不同的索引条目添加到其中。这称为多键索引,每个文档都将被链接到索引中的多个值。使用检查explain()就会看到其中提到了多值索引。

示例:

  • 创建升序或降序索引。
//插入数据
db.media.insert({"Type":"CD", "Artist":"Nirvana", "Title":"Nevermind", "Genre":"Grunge", "Releasedate":"1991.09.24", "Tracklist":[{"Track":"1", "Title":"You Know You're Right", "Length":"3:38"}, {"Track":"5", "Title":"Smells Like Teen Spirit", "Length":"5:02"}]})
db.media.insert({"Type":"Book", "Title":"Definitive Guideto MongoDB 3rd ed.", "ISBN":"978-1-4842-1183-0", "Publisher":"Apress", "Author":["Hows, David", "Plugge, Eelco", "Membrey, Peter", "Hawkins, Tim"]})

//在Type字段上创建一个简单的升序二叉树索引
> db.media.createIndex({"Type": 1})
//在Tracklist.Title字段上创建一个简单的降序二叉树索引
> db.media.createIndex({"Tracklist.Title": 1})

//查看索引
> 
> db.media.getIndexes()
[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"Type" : 1
		},
		"name" : "Type_1"
	},
	{
		"v" : 2,
		"key" : {
			"Tracklist.Title" : 1
		},
		"name" : "Tracklist.Title_1"
	}
]

2.2、创建复合索引

  • 为查询中所有用到的字段都分别创建索引(即为每个字段都创建一个索引)。这种方式可能会加快查询的速度,但会降低添加和删除数据的速度,因为在每次执行修改操作时都要更新这些索引。
  • 查询过程只会使用一个索引,所以添加许多小索引通常并不会改善查询性能。
  • 复合索引提供了一种减少集合中索引数目的方法,它允许将多个字段结合在一起创建个索引,所以应该尽量使用复合索引。
  • 复合索引有两种:子文档索引和手动定义的复合索引。
  • 可以在查询时不使用所有复合索引键的情况下使用复合索引。因此,可以构造出一组复合索引,覆盖到所有希望在集合中执行的查询,而不需要单独索引每个字段(从而避免对插入/更新操作的性能造成负面影响)。
  • 复合索引在使用索引进行排序时就没那么有用了。排序并不善于利用复合索引,除非数据项的列表和排序与索引结构匹配。

1、创建简单复合索引

  • 使用子文档中的字段作为索引键时,构建多键索引的字段顺序,要与它们在子文档中的顺序相同。许多情况下,这种方式都无法对创建索引的过程进行充分控制。
    • 为解决这个限制,并保证查询使用以目标方式构建的索引,需要查询的文档结构与创建索引所使用的子文档结构相同。
    • 还可为所有用于创建复合索引的字段显式命名,然后指定这些字段的结合顺序。

示例1:

//插入数据
db.media.insert({"Type":"Book", "Title":"Definitive Guideto MongoDB 3rd ed.", "ISBN":"978-1-4842-1183-0", "Publisher":"Apress", "Author":["Hows, David", "Plugge, Eelco", "Membrey, Peter", "Hawkins, Tim"]})
db.media.insert({"Type":"CD", "Artist":"Nirvana", "Title":"Nevermind", "Genre":"Grunge", "Releasedate":"1991.09.24", "Tracklist":[{"Track":"1", "Title":"You Know You're Right", "Length":"3:38"}, {"Track":"5", "Title":"Smells Like Teen Spirit", "Length":"5:02"}]})

//创建复合索引
> db.media.createIndex({"Tracklist.Track": 1, "Tracklist.Length": 1})

//使用符合索引
> db.media.find({"Tracklist.Track": "1", "Tracklist.Length":"3:38"}).explain('executionStats')

示例2:

//在orderDate字段(按升序)和zipcode字段(按降序)上创建复合索引。
db.collection.createIndex( { orderDate: 1, zipcode: -1 } )
//state字段(按升序)和zipcode字段(散列)上创建复合索引(从MongoDB 4.4开始,复合索引可以包含单个散列)
db.collection.createIndex( { "state" : 1, "zipcode" : "hashed" } )

2、MongoDB选择索引的方式

  • 优化器在为查询选择“最佳索引”时考虑的因素?
    • 最优索引必须包括查询的所有过滤字段和排序字段。
    • 查询中任何范围过滤字段或排序字段必须在相等字段的后面(如果当前查询条件有多个最优索引,则MongoDB使用先前成功的计划,除非其执行性能不如另一个计划)。

示例:

//插入数据
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3})
db.student.insert({"id":2, "name": "hh2", "age": 22, "class": 5})
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1})
db.student.insert({"id":4, "name": "hh4", "age": 22, "class": 2})

//创建索引前执行查找
> db.student.find({id: {$gte: 2, $lte: 4}}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 3,              #符合查询条件的文档数
		"executionTimeMillis" : 0,    #查询计划选择和查询执行所需的总时间(以毫秒为单位)
		"totalKeysExamined" : 0,      #扫描的索引条目数
		"totalDocsExamined" : 4,      #在查询执行期间检查的文档数
...

//创建简单索引
> db.student.createIndex({"id": 1})
//执行查找
> db.student.find({id: {$gte: 2, $lte: 4}}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 3,
		"executionTimeMillis" : 0,
		"totalKeysExamined" : 3,
		"totalDocsExamined" : 3,
...
//执行查找,范围和相等查询
> db.student.find({id: {$gte: 2, $lte: 4}, age: 22}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 2,
		"executionTimeMillis" : 0,
		"totalKeysExamined" : 3,
		"totalDocsExamined" : 3,
...

//创建符合索引
> db.student.createIndex({"id": 1, "age": 1})
//执行查找
> db.student.find({id: {$gte: 2, $lte: 4}, age: 22}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 2,
		"executionTimeMillis" : 1,
		"totalKeysExamined" : 3,
		"totalDocsExamined" : 3,
...

//创建索引
> db.student.createIndex({"age": 1, "id": 1})
//执行查找
> db.student.find({id: {$gte: 2, $lte: 4}, age: 22}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 2,
		"executionTimeMillis" : 1,
		"totalKeysExamined" : 2,
		"totalDocsExamined" : 2,
...

3、创建复杂复合索引

  • 创建复合索引时,索引字段的顺序:
    • (1)相等测试:按任意顺序把所有相等测试的字段添加到复合索引中。
    • (2)排序字段:在索引中添加排序字段,其顺序、方向和查询的排序相同。(只有存在多个排序字段,升序/降序才重要)
    • (3)范围过滤器:首先,为基数最低的字段添加范围过滤器(集合中不同的值最少),接着添加基数最低的范围过滤器,直到基数最高的范围过滤器为止。
  • 如果相等测试字段或范围过滤器字段没有过滤掉90%的文档,就可以省略它们,以减少索引的大小。
  • 如果集合上有几个索引,就可能需要提示Mongo使用正确的索引。

2.3、在后台创建索引

db.collection.createIndex(keys, {background: true})
  • 使用createlndex()函数创建索引时,服务器必须读取集合中的所有数据并创建指定的索引。
    • 默认情况下,索引构建将在前台完成,集合所在数据库上的所有操作都将被阻塞,直至索引操作完成。
    • MongoDB因此引入了一个特性,它允许索引构建在后台执行。在后台构建索引的过程中,其他连接在数据库上的操作(读和写)并不会被阻塞。一旦索引创建完成,所有需要使用索引的查询都将立即使用它。值得注意的是,索引在后台构建时将耗费更长的时间。
  • 如果创建索引的操作已经挂起或者花费了太长时间,那么可以终止该操作。终止该操作后,已完成的部分索引也将被删除,防止数据库中出现损坏或无关的数据。
//查看目前MongoDB实例中运行的所有操作的列表(获取操作ID)
db.currentOp()
//通过操作ID终止操作
db.killOp(opid)

示例:

> db.student.createIndex({"age": 1, "name": 1}, {background: true})

2.4、创建唯一索引

1

#                                                                                                                          #

标签:创建,db,索引,字段,文档,id,MongoDB09
From: https://www.cnblogs.com/maiblogs/p/16709685.html

相关文章

  • 极客--普通索引和唯一索引应该怎样选择?
    不同的业务场景下,应该选择普通索引还是唯一索引?查询过程selectidfromTwherek=5这个查询语句在索引树上查找过程:显示通过B+树从树根开始,按层搜素叶子节点,也就是......
  • MySQL-索引
    MYSQL之索引本章包含索引概述,索引结构,索引语法,索引分类,SQL性能分析,索引使用,索引设计原则!索引概述介绍(1)索引(index)是帮助MySQL高效获取数据的数据结构(有序)。......
  • Postgresql索引介绍
    参考地址:PostgreSQL9种索引的原理和应用场景-阿里云开发者社区(aliyun.com)1、btreeb-tree适合所有的数据类型,支持排序,支持大于、小于、等于、大于或等于、小于或等于......
  • SQLServer第九章:视图与索引
    视图:查看来自于一个或多个列的列的集合,一张虚拟表,视图中并不存放任意数据,只存放select语句 查看视图最基本的代码:select*from表名返回一个虚拟表索引:提高查......
  • 极客--深入浅出索引
    索引是怎样工作的?索引的出现是提高数据查询效率,就像教科书中的目录一样。索引的常见模型哈希表哈希表是一种以键值存储的结构,我们只需要输入待查找的键即为key,就可......
  • 百度站长平台提供链接索引的自动提交
    百度站长平台提供链接索引的自动提交JS代码脚本。用百度自己的话讲:JS链接推送代码以网页为最小对象,服务于全平台多终端,PC站和移动站均可使用。安装代码的页面在任意平台......
  • 倒排索引的理解
    https://blog.csdn.net/qq_39144436/article/details/124509108搜索的核心目标实际上是保证搜索的效果和性能,为了高效的实现全文检索,我们可以通过倒排索引来解决。倒排......
  • 分布式搜索引擎02
    分布式搜索引擎02 在昨天的学习中,我们已经导入了大量数据到elasticsearch中,实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。所以今......
  • 导致索引失效的几种情况
    1.用!=或者<>导致索引失效select*fromtable1wherename!='zhangsan'select*fromtable1wherename<>'zhangsan'2.函数导致的索引失效  如果使用......
  • 深入理解全文搜索引擎 Elasticsearch
    注:本文摘抄自:https://mp.weixin.qq.com/s/Q-QV86XntKniQlMohIaexQ生活中的数据搜索引擎是对数据的检索,所以我们先从生活中的数据说起。我们生活中的数据总体分为两种:结......