zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

mongo索引

索引 mongo
2023-09-14 09:06:35 时间

mongo索引

索引的基本理解

索引实际就是对指定字段进行排序的数据结构 。

基于B-Tree的结构提升查询速度。 (时间复杂度logn)

复合键索引可以对多个字段进行排序。复合键索引只能支持前缀子查询

例如创建的复合查询为(a,b,c),匹配的时候只能按照从左往右的形式,比如

(a),(a,b)但是不能对(b,c)或者(b)不能加速索引。

查询索引:db.collection.getIndexes(),
创建索引:db.collection.createIndex(),
删除索引:db.collection.dropIndex()

索引的创建

默认索引 _id

db.collection.createIndex({name:1}) #1从小到大排序

返回值

numIndexesBefore:1

numIndexesAfter:2

查询索引:db.collection.getIndexes()

创建复合键索引

db.collection.createIndex({name:1,balance:-1}) #1从小到大排序

多键索引

包含数组元组的字段创建索引。创建方法和单键的一致。

指定为后端形式创建索引

存在大量数据的集合上创建索引是非常耗时的,而且在创建索引的时候,会阻塞所有的读和写请求,一致到索引创建完成。这个时候可以通过设置为在后端创建,指定background为true避免阻塞。

索引的效果

db.collection.explain()

看结果里的

queryPlanner: 然后看winningPlan性能最好的执行方式,然后看stage字段

COLLSCAN(遍历整个集合)最不希望看到结果,效果最差的搜索方式。

如果创建了索引

首先发现其stage为FETCH,然后下面会发现inputStage的stage为 IXSCAN(全称index scan),根据索引查询,这正是我们的目的,通过创建索引提高查询效果。keyPattern字段可以看到对应的索引。indexName就是索引的名字。

如果只返回加了索引的字段效率会进一步提高。

winningPlan的stage为PROJECTION,然后inputStage的stage为 IXSCAN。

这种情况是最优的查询效果了。

索引的唯一性

创建具有唯一性的索引

db.collection.createIndex({name:1},{unique:true}) #1从小到大排序

要求该字段不能出现重复值,如果想创建就必须删除重复的字段。如果文档中没有name字段,而对其创建了唯一性索引,再插入第一个文档的时候会给index设置为null,然后在创建第二文档的时候如果还没有name字段,将报错。

索引的稀疏性

只将包含索引键字段的文档加入索引中(即使索引字段值为null),对于不含有索引字段的

文档就不会再查询了,大大降低了索引的存储空间。

db.collection.createIndex({name:1},{sparse:true}) 

如果索引既有唯一性,又具有稀疏性,就可以保存 多篇 缺失索引值的文档了。

db.collection.createIndex({name:1},{unique:true,sparse:true}) 

不会再出现上面唯一性说的报错问题了。

索引的生命周期

针对日期字段,可以指定索引的时间,如果到时间自动删除索引。

db.collection.createIndex({crawl_time:1},{expireAfterSeconds:20}) 

在crawl_time字段上创建一个生存时间是20秒的索引。20s之后文档会被删除。

但是这个特性只适合单键索引,不适合复合键索引。

当索引键是包含日期元素的数组字段时,数组中最小的日期将被用来计算文档是否已经过期。因为数据库使用一个后台线程来检测和删除过期的文档,删除操作可能有一定的延迟。

文本索引

创建索引

如果经常对某个字段进行字符串的搜索,为了提高速度可以使用该类型索引。

可以对一个集合的一个或者多个字段设置文本索引,但是一个集合只能有一个文本索引。例如:

db.stores.createIndex({ name: "text")

给name字段创建文本索引,结果正常。

db.stores.createIndex({description: "text"})

发现出现错误:IndexOptionsConflict.

通过索引的名字删除索引以后重新插入一个含有上面两个字段的复合索引。

db.stores.createIndex( { name: "text", description: "text" } )

发现可以成功插入。

查询索引

db.stores.getIndexes()

得到索引的信息,关键是name。

删除索引

根据上面的name,进行删除

db.stores.dropIndex("name_text")

$text

使用 $text 查询操作符的前提,必须是在一个有 text index 的集合上执行文本检索。

如果不存在文本索引会出现错误:text index required for $text query

$text 将会使用空格和标点符号(例如:逗号)作为分隔符对检索字符串进行分词, 并且对检索字符串中所有的分词结果进行一个逻辑上的 OR 操作。

例如,您可以使用下面的查询语句来找到所有包含 “coffee”, “shop”, 以及 “java” 列表中任何词语的商店:

db.stores.find({$text: {$search: "java coffee shop" } } )

本次查找是在整个集合中进行查找,通过explain可以查看mongo查询语句的速度

看到查询状态为IXSCAN,可以知道目前是最佳速度了。

精确查询

如果查询的字符串直接有空格,但是想完全匹配可以使用双引号。

db.stores.find({$text: {$search: "java \"coffee shop\"" } } )

记得将引号里面字符串引号使用\转义。

词语排除

为了排除一个词语,您可以在前面加上一个 “-” 字符。例如,为了找到所有包含 “java” 或者 “shop” 但是不包含 “coffee” 的商店,使用下面的命令:

db.stores.find( { $text: { $search: "java shop -coffee" } } )

排序

聚合用的暂时不研究