mongodb索引及查询优化分析

Mongodb索引及查询优化分析

创建索引

    db.collection.createIndex(keys, options)
  • 参数说明:
    • keys: {FieldNameOne:ascending,… FieldNameN:ascending}: ascending 设为1 标识索引升序,-1降序
    • options : 设置索引选项,如设置名称、设置成为唯一索引

唯一(_id)索引

  • MongoDB都会自动生成一条唯一的_id字段

  • 唯一索引会阻止应用插入被索引键上的值是重复值的documents

  • 不能再已经有重复数据的字段上建立唯一索引

      db.collections.createIndex({“FieldName”: 1或-1},{“unique”:true}) 
    

单键索引

  • 在一个键上创建的索引就是单键索引

      db.collection.createIndex({'fieldName':1/-1});
    

复合索引

  • 查询多个条件时,建立复合索引

  • 在多字段上建唯一索引会强制要求复合键值的唯一性,而不是每个键的唯一性

      db.collection.createIndex({'fieldName_one':1/-1,'fieldName_n..':1/-1});
    
  • 总结:

    • 查询条件只是复合索引key中部分字段时,如果想要复合索引起到优化的作用则必须包含创建复合索引时指定的第1个字段;
    • 可以指定在索引的所有键或者部分键上排序。但是,排序键的顺序必须和它们在索引中的排列顺序一致sort中指定的所有键的排序顺序(例如递增/递减)必须和索引中的对应键的排序顺序完全相同, 或者 完全相反。

多键索引

  • 多键索引与单键索引创建形式相同,区别在于字段的值,如:数组

      db.collection.createIndex({'arrayFieldName':1/-1});
    

稀疏索引

    db.collection.createIndex({“FieldName”:1},{“sparse”:true})
  • 在一个字段上创建稀疏索引,索引会跳过所有不包含被索引键(字段)的文档在执行查询 { 被索引键:{$exists:false}},不会使用该稀疏索引,除非显示指定hint({被索引键:1})

      db.scores.createIndex( { score: 1 } , {sparse:true} )
      db.scores.find( { score:{$exists:false}}).hint({score:1}).explain()
    
  • 总结

    • 在某一个被创建了稀疏索引字段上执行exists:false查询时,需要显示指定hint,其索引才会起作用;而执行 exists:true查询时,则不需要。
    • 在字段上创建普通索引,如果文档不含该字段这其索引值会被设为null,而稀疏索引会跳过该文档;这就是说使用该索引扫描集合时稀疏索引会比普通索引少。

局部索引(Partial Index)

    db.collection.createIndex(
    {“FieldName”: 1/-1,…”FieldNameN”: 1/-1},
    {“partialFilterExpression”:{partialFilterExpression }})
    
    db.contacts.createIndex(
    { name: 1 },
    { partialFilterExpression: { name: { $exists: true } } }
    )
  • $eq
  • $gt, $gte, $lt, $lte
  • $exists: true

TTL(过期)索引

  • 在一段时间后会过期的索引,在索引过期后,相应的数据会被删除,适合存储在一段时间之后会失效的数据;

  • 存储在过期索引字段的值必须是指定的时间类型,必须是ISODate或者ISODate数组,不能使用时间戳,否则不能自动删除;

  • 如果指定了ISODate数组,则按照最小的时间进行删除;

  • 过期索引不能是复合索引,因为不能指定两个过期时间;

  • 删除时间是不精确的:删除过程是由MongoDB的后台进程每60s跑一次的,而且删除也需要一定时间,所以存在误差。

      db.collection.createIndex({'dateTimeField':1},{expireAfterSeconds:100(秒)});
    

全文索引

  • 对字符串与字符串数组创建全文课搜索的索引;

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

  • 每次查询只能指定一个$text查询$text查询不能出现在$nor查询中;

  • 查询中如果包含了$text, hint不再起作用

      db.file.find({$text:{$search:'mongo'},'status.pub':true},{ score: { $meta: "textScore" } }).sort( {score: { $meta: "textScore" }}  )
    

地理空间索引

  • 2D索引,用于存储和查找平面上的点

  • 2Dsphere索引,用于存储和查找球面上的点

      db.collection.createIndex({w:"2d"})
    
    • 使用$near 查询距离某个点最近的点 ,默认返回最近的100个点

    • 可以使用$maxDistance:x 限制返回的最远距离

        db.collection.find({w:{$near:[x,y]}})
        db.collection.find({w:{$near:[x,y],$maxDistance:z}})
      
    • 使用$geoWithin 查询某个形状内的点

哈希索引

查询性能分析

    db.collection.find({}).explain("queryPlanner"/"executionStats"/"allPlansExecution")
    db.file.createIndex({'tag.self':1})
    db.file.find({'tag.self':{$in:['node']}}).explain("executionStats")

性能指标

  • winningPlan.stage = FETCH(根据索引去检索指定document )
  • winningPlan.inputStage.stage = IXSCAN(索引扫描)
  • totalKeysExamined 索引扫描条目
  • totalDocsExamined 文档扫描条目
  • nReturned 查询返回的条目

总结:

  • 排序操作可以通过从索引中按照索引顺序获取文档的方式来保证结果的有序性。如果查询计划器(planner)无法从索引中得到排序顺序,那么它将需要在内存中排序(winningPlan.stage=SORT)结果。
  • 在多个字段上做排序时需要使用复合索引
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容