zoukankan      html  css  js  c++  java
  • Mongo Index

    摘要

    mongo 的索引非常强大,和关系型数据库索引没什么区别。这里主要介绍本人在mongo索引上的犯的错。

    索引种类

    1.单字段索引
    2.复合索引
    复合索引各个字段的顺序应该是精确匹配字段(=xxx),排序字段(避免在内存中排序,使用index排序),范围查询字段

    如db.book.find({company: ‘xxx’, age:{$lt:30}).sort({name:1})
    db.book.find().explain("executionStats")可以很好的列出查询执行计划。
    总共有四个重要参数:
    executionTimeMills:查询执行的时间
    nReturned: 返回的文档数
    totalKeysExamined: 索引扫描数
    totalDocsExamined: 文档扫描数

    当然希望nReturned数目=totalKeysExamined
    不扫描文档。(后面不挂着数据,index及数据)

    或者nReturned = totalKeysExamined = totalDocsExamined
    如果有排序,为了不让排序在内存中进入,在nReturned = totalDocsExamined的基础上,totalKeysExamined可以大于nReturned。对于大数据量的内存排序会非常消耗性能

    如果我们创建一个复合索引是db.book.ensureIndex({company:1,age:1,name:1})
    这时候nReturned = totalKeysExamined = totalDocsExamined
    。因为查询会用到index,不需要额外的文档扫描。但是会有SORT stage。即在内存中排序。

    尝试加一个index,在排序字段放在扫描字段前面
    db.book.ensureIndex({company:1,name:1,age:1})
    这时候发现mongo选择了新的index

     "indexBounds" : {
             "company" : [
                     "["a", "a"]"
             ],
             "name" : [
                     "[MinKey, MaxKey]"
             ],
             "age" : [
                     "[-1.#INF, 30.0)"
             ]
     },

    且执行计划中有reject SORT排序

    "rejectedPlans" : [
            {
                    "stage" : "SORT",
                    "sortPattern" : {
                            "name" : 1
                    },
    

    这时候nReturned = totalDocsExamined < totalKeysExamined 多扫描了index。但是是值得的。
    如{name:1,address:1},包含的是两个查询

    db.book.find({name:"xxx"})
    db.book.find({name:"xxx",address:"xxx"})

    但是如果你的查询不是范围查询。而是精确匹配字段。那还是使用原来的index。因为这时候排序字段用到了index查询,不需要SORT阶段了

    db.book.find({company:'a',age:30}).sort({name:1}).explain("executionStats")
     "indexBounds" : {
             "company" : [
                     "["a", "a"]"
             ],
             "age" : [
                     "[30.0, 30.0]"
             ],
             "name" : [
                     "[MinKey, MaxKey]"
             ]
     },
    

    3.多键索引
    如array索引

    4.唯一索引
    db.book.createIndex({“name”:1},{“unique”:true})
    mongo 默认创建的不是唯一索引,需要显示指定。唯一索引会对数据进行校验,不允许重复数据。

    1. sharding cluster 索引
      索引是在各个shard上面单独建立的,不是全局的。
      sharding cluster 环境,只允许_id,和shard key建立unique index.因为unique index 需要shard 之间通信,违背了shard 设计理念。所以需要避免

    注意
    1. 当一个collection上面有多个index
    某个查询可能命中多个index,这时候mongo是如何选择索引的呢。

    首先mongo会对某类类似查询语句在可能命中的index都执行一遍,并行执行的,最早返回100个结果找出最优的index,然后记住这类查询所用到的索引。以后查询操作就使用这个索引。当有index更改时,再去更改这个值。

    1. 当有一个复合索引
      {name:1,address:1,email:1}

    这时候有一个新的查询{name:xxx,address:xxx,phone:xxx}
    可以用到已经创建的复合索引。这时候你会不会单独在创建一个索引呢。
    优势是这个查询也很快,缺点是多了一个index,减弱了插入性能。

    这个可能需要衡量前两个字段过滤掉了多少数据,phone这个字段占剩下数据量的多少来决定需要创建什么样的index.

    array index

    mongo 可以对array建立index,注意是将index中的每个元素都作为index key,进行索引。所以对array建立index一定要十分小心,很容易导致index size 很大。另外mongo支持指定array某一列进行查询。

    test.book
    {
        _id:1,
        name:english,
        address:[addr1,addr2]
    }

    db.book.find({“address.0”:”addr1”})
    当对address创建index,这样的查询是用不到index的。只有基于array的查询,index才能有效。
    mongo并没有那么神奇的在创建index的同时还保留列数。

    shard key index

    • 表中有数据
      表中有数据再创建shard key,需要首先创建对应的index,才能去创建shard key
    • 表中无数据
      表中无数据,创建shard key的同时,mongo会自动创建一个对应字段的index
    sh.shardCollection("test.book",{name:1,address:1})

    会自动创建index

    {name:1,address:1}

    mongo index VS cassandra secondary index

    1.query 过程
    cassandra query,首先根据partitioner key去找对应partition,partition中的数据是按照clustering key排序的。注意是按照clustering key排序的,clustering key这个字段 不是index。

    mongo(sharding cluster) query,首先根据给定的shard key去找在哪个节点上,然后将请求发送到此节点。进行查找。
    如果你的query case是

    db.book.find({name:"xxx",address:"xxx"})

    而shard key是name。此外再单独为address建立一个index。这时候你的query其实是命中的address 的单字段index。而不是预想的已经将name数据过滤了。这点和cassandra有很大的不同

    2.范围
    cassandra secondary index 是local的,在每个节点上。
    mongo 的index是全局的。
    mongo sharding cluster 环境,index也是在各个shard上独立创建的。

    参考

    http://www.mongoing.com/eshu_explain3

  • 相关阅读:
    沿着河边走,环城60公里
    与客家土楼的约会(叶剑英故居福建)
    与客家土楼的约会(增城河源)
    与客家土楼的约会(东源龙川)
    C#几个经常犯错误
    C# 获取当前路径方法
    C# Stopwatch与TimeSpan详解
    话说程序员成熟的标志
    C#开源项目介绍
    C#各种加密算法的研究
  • 原文地址:https://www.cnblogs.com/stoneFang/p/6715279.html
Copyright © 2011-2022 走看看