mongodb索引学习

文章一:https://blog.csdn.net/xiamoyanyulrq/article/details/81456894 

建立情况:

1.表的主键、外键必须有索引;

2、数据量超过300的表应该有索引;

3、经常与其他表进行连接的表,在连接字段上应该建立索引;

4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;

5、索引应该建在选择性高的字段上;

6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;

7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:  A、正确选择复合索引中的主列字段,一般是选择性较好的字段;  B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;  C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;  D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;  E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;

8、频繁进行数据操作的表,不要建立太多的索引;

9、删除无用的索引,避免对执行计划造成负面影响;  

以上是一些普遍的建立索引时的判断依据。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。

索引类型:

_id索引

主键_id会生成一个默认的索引,此索引是唯一并且不能删除的。

单键索引:

最普通的索引,key对应的值为一个单一的值,如字符串,数字或日期【a:”already”】

多键索引:

值具有多个记录,如数组【a:[1, 2, 3]】

文档索引

全文索引:

文章一:http://www.360doc.com/content/17/1211/13/33260087_712076317.shtml 

不适用全文索引:查找困难,效率低下,需要正则匹配,逐条扫描。

适用于:简单查询即可查询需要的结果

 

对字符串与字符串数组创建全文可搜索的索引

    1. 字符串:key:”你好”
      1. 通过db.col.find({$text:{$search:”你好”}})可以查询出来数据,因为:key这个值中,你好被系统当作了一个完整的词。语句搜索“你好”== key对应的“你好”
      2. 通过db.col.find({$text:{$search:”你”}})或者db.col.find({$text:{$search:”好”}})不可以查询出来数据。因为:你好被当作一个完整的词,语句搜索“你” != “你好”,无法查出
      3. Key如果值为:“你 好”,即用空格分隔,相当于吧“你好”进行拆词,拆分成“你”和“好”,这样我们在用上面的“你”或者“好”就能查询出该条数据,但是查询条件“你好”就没有办法查询出该条数据了,因为“你好”!=“你”或者“好”。除非,拆词将其拆分为,“你”“好”“你好”才可以通过这多个查询条件查询出该条数据
      4. 查询条件db.col.find({$text:{$search:”你 好”}})这样,“你 好”被空格分开,就相当于去查询匹配“你”或者“好”的数据。
    2. 字符串数组:key:[“你”,“好”]。 相当于key:”你 好”,查询时的规则与此相同

创建方式:

    1. 在集合中一个指定字段创建全文索引:db.col.createIndex( {key :”text”});
    2. 在集合中多个指定字段创建全文索引: db.col.createIndex( {key1 :”text”,key2:”text”})
    3. 在集合所有字段创建全文索引:db.col.createIndex( {“$**” :”text”})

全文索引的查找:

1:使用全文索引查询不需要指定全文索引的字段名字——直接使用$text,$search即可。 db.col.find({$text:{$search:”aaa”}})

2:在MongoDB中每个数据集合只允许创建一个全文索引,不过这个全文索引可以针对一个、多个、全部的数据集合的字段来创建。

3:查询多个关键词,可以使用空格将多个关键词分开——空格——或的关系 db.col.find({$text:{$search:”aa bb cc”}})

4:指定不包含的字段使用-来表示—— -:非的关系 db.col.find({$text:{$search:”aa -bb”}})

5:引号包括起来代表与的关系—— \”\”:与的关系 db.col.find({$text:{$search:”\”aa\”\”bb\””}});【详解:意思查找被设置为全文索引的字段必须要同时有aa与bb值,才可以被查询出数据。但是此处经过测试:

data1:key:”我是谁 哈哈” data2:key:”我 是 谁 哈哈”

查询条件1:”\”我\”” 结果:data2

查询条件2: ”\”哈哈\”\”我\”” 结果:data1,data2,然而按照 与关系规则与拆词规则,data1“我是谁”被作为了一个整词,他只有“哈哈”匹配但是“我”不匹配,data2属于完全匹配

查询条件3:“\”哈哈\”\”我是\”” 结果:data1,

最终得出结论:与关系条件下,只要有一个数据值不符合
(1.“我是谁“,条件“我”或者“我是”,我包含在我是谁中,虽然不符合拆词规则,但仍包含在其中,仍可去判断其他的数据值是否符合,如有任意一个完全符合,仍可返回此条数据。
  2.”我 是 谁“,条件“我是”,因为词已经被拆分完毕,所以“我 是 谁”不包含“我是”,即完全不匹配,所以此条数据不符合与规则,无需返回)

相似度查询

搜索排序,查询结果与你查询条件越相关的越排在前面。
MongoDB中可以使用$meta操作符完成,格式:{score:{$meta: "textScore"}}

实例:db.col.find({$text:{$search:”aa bb”}},{ score:{$meta: "textScore"}}).sort({score:{$meta: "textScore"}});[根据相似度分钟的高低进行排序,高的在前面]

5.限制条件

·  一个查询只能指定最多一个$text表达式。

·  $text表达式不能跟$nor一起使用。

·  $text表达式跟$or一起使用的情况下,数组必须包含全文索引。[不懂]

·  不能使用hint()强制指定使用全文搜索。

·  在$text表达式中不能使用{$natural:true}进行排序。

·  不能将$text表达式与可以允许不同类型的索引进行组合,例如不能将$text表达式跟$near操作符组合。

·  View不支持全文索引

 

复合索引:

比如 :{a:1,b:1}

查询条件为{a:2},没有b的时候,我们可以理解为复合索引中的“不完整索引”查询

而查询条件为{a:2,b:3},a与b都有,我们就可以理解为复合索引中的“完整索引”查询

使用索引情况:创建复合索引:a,b,c

  1. 使用a,或者a,b/b,a或者a,b,c/c,b,a/b,c,a都可以,只要查询条件包含你创建复合索引的第一个字段即可
  2. 如果不包含默认使用全表查询,stage:COLLSCAN
  1. 查询多个条件时,建立复合索引.
  2. 例如{x:1,y:2,z:3}这样一条数据,要按照x与y的值进行查询,就需要创建复合索引。
  3. 创建:db.xx.createIndex({x:1,y:1})

4.对一张表来说,如果有一个复合索引 on   (col1,col2),就没有必要同时建立一个单索引 on col1;     如果查询条件需要,可以在已有单索引 on col1的情况下,添加复合索引on (col1,col2),对于效率有一定的提高     同时建立多字段(包含5、6个字段)的复合索引没有特别多的好处,相对而言,建立多个窄字段(仅包含一个,或顶多2个字段)的索引可以达到更好的效率和灵活性

5. 对于复合索引,在查询使用时,最好将条件顺序按找索引的顺序,这样效率最高

6. 不要过多用索引,否则对表更新的效率有很大的影响,因为在操作表的时候要化大量时间花在创建索引中

唯一索引:

配置选项unique:true的索引

还有一点需要注意的是,唯一索引的存储值不能超过1024KB,否则不会报错也不会受唯一约束。并且很难对问题进行排查

过期索引/TTL索引:

配置选项expireAfterSeconds:xx,的索引。【xx为数值类型,单位为秒/s】

  1. 存储在过期索引字段的值必须是指定的时间类型,必须是ISODate或者ISODate数组,不能使用时间戳,否则不能自动删除,例如 >db.imooc_2.insert({time:1}),这种是不能被自动删除的
  2. 如果指定了ISODate数组,则按照最小的时间进行删除
  3. 过期索引不能是复合索引。因为不能指定两个过期时间
  4. 删除时间是不精确的。删除过程是由MongoDB的后台进程每60s跑一次的,而且删除也需要一定时间,所以存在误差

地理空间索引

文章一http://www.mongoing.com/mongodb-geo-index-1/ 

文章二https://blog.csdn.net/u012702547/article/details/81027421 

使用:

  1. 创建模型:

Location:{

type: {

      type: String,

      default:  'Point' , // 还可以是其他的类型

      required: true,

    },

    coordinates: {

      type: [ Number ],

      required: true,

    }

}

  1. 创建索引:
    1. Schema.index({location:’2dsphere’})

 

覆盖索引

在使用了索引字段作为查询的条件的情况下,限制返回的字段,使返回的字段为,作为索引的字段。比如作为索引的字段为a,b,限制返回的字段为{a:1,_id:0},【注意主键_id字段,为默认返回字段,需要将此字段限制其返回】,这样就可以直接在索引中查询到我们需要得到的数据,无需通过索引再去文档中进行查询,极大的提高了工作效率。

 

创建获取:

语法:

    1. db.collection.createIndex(keys,options)
    2. 栗子:db.col.createIndex({key:1,key2:-1},{background:true})
    3. 1是ASC,按从小到大排序,-1时DESC,按从大到小排序

Options详细参数讲解:

    1. Background:建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false
    2. Unique:值为true的话,设置的基础索引或者复合索引的值不能重复,即值是唯一不可重复的。 默认为false。
      1. 基础索引:原有a:1,新建a:1,会报错
      2. 复合索引:原有a:1,b:2,新建a:1,b:3,不会报错,新建a:1,b:2报错
    3. Name:指定创建索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
    4. Sparse:与unique一同使用。
    5. expireAfterSeconds:指定一个以秒为单位的数值,完成TTL设定,设定集合的生存时间。【设定此选项时,索引需要为一个时间类型的字段即Date类型】
    6. weight:索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
    7. v/default_language/language_override不常用,如需了解手动查询

其他语法:

    1. 获取集合对应的所有索引:db.col.getIndexs()
    1. 查看集合索引大小:db.col.totalIndexSize()
    1. 删除集合对应的所有索引:db.col.dropIndexs()
    2. 删除集合对应的指定索引:db.col.dropIndex(‘name’)

获取数据

 

 

索引子文档

Db.col.createIndex({“key.field1”:1,” key.field2”:1});

Explain查询计划

文章一https://blog.csdn.net/u012702547/article/details/80606614 

方法:db.col.find().explain()

部分参数解释:从inputStage下的stage到winningPlan下的stage:是搜索顺序,常见的有COLLSCAN/全表扫描、IXSCAN/索引扫描、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询

IXSCAN:检索索引。

FETCH:通过索引检索实际的文档(比如索引为a,我们通过a去搜索,得到了索引中对应的a,但索引表中置存储了字段a,并未存储数据的其他字段,此时我们需要去文档查询,这一步骤就叫FETCH)

COLLSCAN:直接搜表整个集合

PROJECTION:投影。即当我们限制查询出来的字段时(例如:find({a:2,b:3},{a:1}),只显示a字段数据,即为限制查询);此时stage就为:PROJECTION

通过explain计划中的的多个stage的值进行判断是否使用了索引:如果stage等于过IXSCAN那么此次搜索就使用了索引

 

Hint::强制使用某个索引进行查询

概述:查询条件包括多个索引,可以通过hint只选择某一个索引进行筛选查询。

文章一https://blog.csdn.net/wanght89/article/details/77658280 

使用情况:根据实际情况来判断是否需要强制使用某索引执行,具体可以通过explain(true)来得到executionStats,通过其中的totalDocsExamined字段,来判断查询数据条数的多少,一般查询的条数越少性能越好,或者通过executionTimeMillis(执行时间)字段来判断。

这里的单键索引,我们暂时理解为只有一个字段的索引比如索引{a:1},{b:1},【暂时对於单键无法区分清楚,有疑惑】

  1. 假如a与b为两个单键索引,a索引的名字为aa,b索引的名字为bb,我们想只使用a索引来参与搜索
    1. 语法: db.col.find({a:2,b:3}).hint({a:1})或者db.col.find({a:2,b:3}).hint(“aa”)。【如果不强制用hint,那么默认会同时调用a索引与b索引一起参与搜索】
  2. 假如:复合索引:{a:1,b:1},单键索引{c:1},名字为 ab和cc,我们想只使用第一个{a:1,b:1}索引来强制查询
    1. 语法: db.col.find({a:2,b:3,b:4}).hint({a:1,b:1})或者db.col.find({a:2,b:3}).hint(“ab”)【不能只输入hint({a:1}),因为索引表中没有创建这个单键索引,存在的是{a:1,b:1}这个复合索引,不能拆分出来】

索引局限性:

  1. 尽管到目前为止我们已经在课程中研究了索引的许多优点,但索引也存在一些与之相关的缺点或限制。我们在这里阅读:
  2. MongoDB中的单个集合最多只能有64个索引。当文档大小很大时,这就成了一个问题,我们可能不得不打破我们的文档,以涵盖多个集合。
  3. 文档中的完全限定索引名称不能超过128个字符。索引的FQN由<db_name>。<collection-name>。$ <index_name>组成。
  4. 在复合索引中,不能超过31个字段。
  5. MongoDB查询不能同时使用文本和地理空间索引。我们不能将$ text运算符与任何与特殊索引关联的其他运算符组合在一起。例如,$ text运算符和$ near运算符不能一起使用。
  6. 具有2d球体索引的字段只能包含几何数据。因此,允许在平面座标系上使用[x,y]点。对于非几何,如果在此索引中保存任何其他类型的数据,则数据查询操作将失败。
  7. 由于当MongoDB实例运行时,索引中的数据主要存在于RAM中,因此它们会消耗机器上的大量内存。这也使得MongoDB索引非常快。
  8. 默认情况下,MongoDB索引在前台进行。这意味着集合上的所有操作都将被阻止,直到完全构建索引。但是,可以通过在查询中指定后台创建属性来覆盖此行为。
  9. 正则表达式以及 非关系操作符,如:$nin,$not等
  10. 算数运算符,$mod等
  11. $where子句
发布了21 篇原创文章 · 获赞 36 · 访问量 11万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章