mongodb高级知识

mongodb数据库索引管理   https://www.cnblogs.com/shengdimaya/p/6598064.html
1.索引
db.Student.getIndexes():查看表的索引
db.Student.totalIndexSize():查看索引大小
db.Student.ensureIndex({"age":1},{background:true}) 创建索引
db.Student.createIndex({"age":1},{background:true,name:"age"}):创建索引
注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。
db.Student.createIndex({"name":1},{background:true,unique:true}):创建唯一索引,插入时如果name已存在则会报错。在默认情况下创建的索引均不是唯一索引。如果插入的name为null,null也不能重复,第二次插入null会报键重复。
db.Student.createIndex({"age":1,"name":-1},{background:true,,unique:true}) : 创建复合唯一索引
数字1表示age键的索引按升序存储,-1表示name键的索引按照降序方式存储。
如果在为已有数据的文档创建索引时,background:true,这样的创建时就不会阻塞其他操作

随着集合的增长,需要针对查询中大量的排序做索引。如果没有对索引的键调用sort,MongoDB需要将所有数据提取到内存并排序。因此在做无索引排序时,如果数据量过大以致无法在内存中进行排序,此时MongoDB将会报错。

db.Student.dropIndex("age"):删除索引
db.Student.dropIndexes():删除除了主键索引以外的其他索引
使用场景
每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引。
内存(RAM)使用
由于索引是存储在内存(RAM),你应该确保该索引的大小不超过内存的限制。
如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。
索引失效:
    正则表达式及非操作符,如 $nin, $not, 等。
    算术运算符,如 $mod, 等。
    $where 子句
所以,检测你的语句是否使用索引是一个好的习惯,可以用explain来查看。
索引键限制

从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。
插入文档超过索引键限制

如果文档的索引字段值超过了索引键的限制,MongoDB不会将任何文档转换成索引的集合。与mongorestore和mongoimport工具类似。
最大范围
    集合中索引不能超过64个
    索引名的长度不能超过128个字符
    一个复合索引最多可以有31个字段
    
ObjectID使用12字节的存储空间,是一个由2416进制数字组成的 BSON 类型数据,有以下格式:
    前4个字节表示时间戳  ObjectId("5349b4ddd2781d08c09890f4").getTimestamp() 可以获得文档的创建时间。
    接下来的3个字节是机器标识码
    紧接的两个字节由进程id组成(PID)
    最后三个字节是随机数。
一个字节占8位,一个16进制数占4位,即是0.5字节。

2.集群
mongodb集群搭建有三种方式。
(1)、Master-Slave模式 主从模式当主机宕机从机无法自动切换为主机,需要手动切换,十分繁琐,且会造成服务中断,官方已不推荐
(2)、Replica-Set方式 副本集故障可以自动切换,如果主节点发生故障,那么会启用备节点,当主节点修复之后,主节点再次恢复为主节点,备节点不再是主节点的角色。副本集的方式还需要一个角色,那就是仲裁节点,它不存储数据,他的作用就是当主节点出现故障,选举出备节点作为主节点,继续保证集群可用。客户端连接时只连接主节点或者备节点,不用连接仲裁节点。
mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
(3)、Sharding方式 分片
当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。
分片集群主要由三个模块组成:
Shard:用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障
Config Server:mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息。
Query Routers:前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

explain
参考链接:https://blog.csdn.net/u014231523/article/details/103437913
参考链接:https://blog.csdn.net/user_longling/article/details/83957085
db.collection.find().explain()
verbose 参数表示执行计划的输出模式。有三种:queryPlanner,executionStats,allPlanExecution
模式名字 描述
queryPlanner 执行计划的详细信息,包括查询计划、集合信息、查询条件、最佳执行计划、查询方式和 MongoDB 服务信息等
exectionStats 最佳执行计划的执行情况和被拒绝的计划等信息
allPlansExecution 选择并执行最佳执行计划,并返回最佳执行计划和其他执行计划的执行情况
阶段操作描述,例:

COLLSCAN 集合扫描
IXSCAN 索引扫描
FETCH 检出文档
SHARD_MERGE 合并分片中结果
SHARDING_FILTER 分片中过滤掉孤立文档
LIMIT 使用limit 限制返回数
PROJECTION 使用 skip 进行跳过
IDHACK 针对_id进行查询
COUNT 利用db.coll.explain().count()之类进行count运算
COUNTSCAN count不使用Index进行count时的stage返回
COUNT_SCAN count使用了Index进行count时的stage返回
SUBPLA 未使用到索引的$or查询的stage返回
TEXT 使用全文索引进行查询时候的stage返回
PROJECTION 限定返回字段时候stage的返回

queryPlanner
db.Student.find({“name” : “zhangsan5”}).explain(“queryPlanner”)

{
    "queryPlanner" : {
        "mongosPlannerVersion" : 1,
        "winningPlan" : {
            "stage" : "SINGLE_SHARD",
            "shards" : [ 
                {
                    "shardName" : "shard1",
                    "connectionString" : "shard1/10.1.36.30:27017,10.1.36.31:27017",
                    "serverInfo" : {
                        "host" : "localhost.localdomain",
                        "port" : 27017,
                        "version" : "4.0.13",
                        "gitVersion" : "bda366f0b0e432ca143bc41da54d8732bd8d03c0"
                    },
                    "plannerVersion" : 1,
                    "namespace" : "bsstest.Student",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "name" : {
                            "$eq" : "zhangsan5"
                        }
                    },
                    "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                            "name" : {
                                "$eq" : "zhangsan5"
                            }
                        },
                        "direction" : "forward"
                    },
                    "rejectedPlans" : []
                }
            ]
        }
    },
    "ok" : 1.0,
    "operationTime" : Timestamp(1634116708, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1634116708, 3),
        "signature" : {
            "hash" : { "$binary" : "gqTvmR5a9TExnI8nfrIdQsZokjQ=", "$type" : "00" },
            "keyId" : NumberLong(7000009888831111173)
        }
    }
}

plannerVersion 执行计划的版本
namespace 查询的集合
indexFilterSet 是否使用索引
parsedQuery 查询条件
winningPlan 最佳执行计划
stage 查询方式
filter 过滤条件
direction 查询顺序
rejectedPlans 拒绝的执行计划
serverInfo mongodb服务器信息
queryPlanner.namespace 一个字符串,指定运行查询的命名空间(即.)。
queryPlanner.indexFilterSet boolan值,表示MongoDB 对于此query shape 是否使用了索引过滤器。
queryPlanner.winningPlan 文档类型,详细显示查询优化程序选择的查询计划。
winningPlan.stage 阶段名称。每个阶段都有每个阶段特有的信息。 例如,IXSCAN 阶段将包括索引边界以及特定于索引扫描的其他 数据。如果阶段具有子阶段或多个子阶段,则阶段将具有inputStage 或 inputStages。
winningPlan.inputStage 描述子阶段的文档。它为其父级提供文档或索引键。 如果父级只有一个子级,则该字段存在。
winningPlan.inputStages 描述子阶段的数组。子阶段为父阶段提供文档或索引键。 如果父级具有多个子节点,则该字段存在。 例如,$or 表达式或索引交集的阶段消耗来自多个源的输入。
queryPlanner.rejectedPlans 查询优化器考虑和拒绝的候选计划数组。 如果没有其他候选计划,则该数组可以为空。

executionStats
db.Student.find({“name” : “zhangsan5”}).explain(“executionStats”)

{
    "queryPlanner" : {
        "mongosPlannerVersion" : 1,
        "winningPlan" : {
            "stage" : "SINGLE_SHARD",
            "shards" : [ 
                {
                    "shardName" : "shard1",
                    "connectionString" : "shard1/10.1.36.30:27017,10.1.36.31:27017",
                    "serverInfo" : {
                        "host" : "localhost.localdomain",
                        "port" : 27017,
                        "version" : "4.0.13",
                        "gitVersion" : "bda366f0b0e432ca143bc41da54d8732bd8d03c0"
                    },
                    "plannerVersion" : 1,
                    "namespace" : "bsstest.Student",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "name" : {
                            "$eq" : "zhangsan5"
                        }
                    },
                    "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                            "name" : {
                                "$eq" : "zhangsan5"
                            }
                        },
                        "direction" : "forward"
                    },
                    "rejectedPlans" : []
                }
            ]
        }
    },
    "executionStats" : {
        "nReturned" : 2,
        "executionTimeMillis" : 1,
        "totalKeysExamined" : 0,
        "totalDocsExamined" : 23,
        "executionStages" : {
            "stage" : "SINGLE_SHARD",
            "nReturned" : 2,
            "executionTimeMillis" : 1,
            "totalKeysExamined" : 0,
            "totalDocsExamined" : 23,
            "totalChildMillis" : NumberLong(0),
            "shards" : [ 
                {
                    "shardName" : "shard1",
                    "executionSuccess" : true,
                    "executionStages" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                            "name" : {
                                "$eq" : "zhangsan5"
                            }
                        },
                        "nReturned" : 2,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 25,
                        "advanced" : 2,
                        "needTime" : 22,
                        "needYield" : 0,
                        "saveState" : 0,
                        "restoreState" : 0,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "direction" : "forward",
                        "docsExamined" : 23
                    }
                }
            ]
        }
    },
    "ok" : 1.0,
    "operationTime" : Timestamp(1634116953, 25),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1634116953, 25),
        "signature" : {
            "hash" : { "$binary" : "mR416yJo3z3VMbyF3VnovkIlhhE=", "$type" : "00" },
            "keyId" : NumberLong(7000009888831111173)
        }
    }
}

字段名称 描述
winningPlan.inputStage 用来描述子stage,并且为其父stage提供文档和索引关键字
winningPlan.inputStage.stage 子查询方式
winningPlan.inputStage.keyPattern 所扫描的index内容
winningPlan.inputStage.indexName 索引名
winningPlan.inputStage.isMultiKey 是否是Multikey。如果索引建立在array上,将是true
executionStats.executionSuccess 是否执行成功
executionStats.nReturned 返回的个数
executionStats.executionTimeMillis 这条语句执行时间
executionStats.executionStages.executionTimeMillisEstimate 检索文档获取数据的时间
executionStats.executionStages.inputStage.executionTimeMillisEstimate 扫描获取数据的时间
executionStats.totalKeysExamined 索引扫描次数
executionStats.totalDocsExamined 文档扫描次数
executionStats.executionStages.isEOF 是否到达 steam 结尾,1 或者 true 代表已到达结尾
executionStats.executionStages.works 工作单元数,一个查询会分解成小的工作单元
executionStats.executionStages.advanced 优先返回的结果数
executionStats.executionStages.docsExamined 文档检查数

allPlansExecution
db.Student.find({“name” : “zhangsan5”}).explain(“allPlansExecution”)

{
    "queryPlanner" : {
        "mongosPlannerVersion" : 1,
        "winningPlan" : {
            "stage" : "SINGLE_SHARD",
            "shards" : [ 
                {
                    "shardName" : "shard1",
                    "connectionString" : "shard1/10.1.36.30:27017,10.1.36.31:27017",
                    "serverInfo" : {
                        "host" : "localhost.localdomain",
                        "port" : 27017,
                        "version" : "4.0.13",
                        "gitVersion" : "bda366f0b0e432ca143bc41da54d8732bd8d03c0"
                    },
                    "plannerVersion" : 1,
                    "namespace" : "bsstest.Student",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "name" : {
                            "$eq" : "zhangsan5"
                        }
                    },
                    "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                            "name" : {
                                "$eq" : "zhangsan5"
                            }
                        },
                        "direction" : "forward"
                    },
                    "rejectedPlans" : []
                }
            ]
        }
    },
    "executionStats" : {
        "nReturned" : 2,
        "executionTimeMillis" : 1,
        "totalKeysExamined" : 0,
        "totalDocsExamined" : 23,
        "executionStages" : {
            "stage" : "SINGLE_SHARD",
            "nReturned" : 2,
            "executionTimeMillis" : 1,
            "totalKeysExamined" : 0,
            "totalDocsExamined" : 23,
            "totalChildMillis" : NumberLong(0),
            "shards" : [ 
                {
                    "shardName" : "shard1",
                    "executionSuccess" : true,
                    "executionStages" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                            "name" : {
                                "$eq" : "zhangsan5"
                            }
                        },
                        "nReturned" : 2,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 25,
                        "advanced" : 2,
                        "needTime" : 22,
                        "needYield" : 0,
                        "saveState" : 0,
                        "restoreState" : 0,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "direction" : "forward",
                        "docsExamined" : 23
                    }
                }
            ]
        },
        "allPlansExecution" : [ 
            undefined, 
            {
                "shardName" : "shard1",
                "allPlans" : []
            }
        ]
    },
    "ok" : 1.0,
    "operationTime" : Timestamp(1634117091, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1634117091, 5),
        "signature" : {
            "hash" : { "$binary" : "h3GLko4/8IoqwCweN+rFbWzRl3I=", "$type" : "00" },
            "keyId" : NumberLong(7000009888831111173)
        }
    }
}

stage状态
状态 描述
COLLSCAN 全表扫描
IXSCAN 索引扫描
FETCH 根据索引检索指定文档
SHARD_MERGE 将各个分片返回数据进行合并
SORT 在内存中进行了排序
LIMIT 使用limit限制返回数
SKIP 使用skip进行跳过
IDHACK 对_id进行查询
SHARDING_FILTER 通过mongos对分片数据进行查询
COUNTSCAN count不使用Index进行count时的stage返回
COUNT_SCAN count使用了Index进行count时的stage返回
SUBPLA 未使用到索引的$or查询的stage返回
TEXT 使用全文索引进行查询时候的stage返回
PROJECTION 限定返回字段时候stage的返回

explain 希望看到的阶段

Fetch+IDHACK

Fetch+ixscan

Limit+(Fetch+ixscan)

PROJECTION+ixscan

SHARDING_FILTER+ixscan

COUNT_SCAN


explain 不希望看到的阶段

COLLSCAN(全表扫描),

SORT(使用sort但是无index),

不合理的SKIP,

SUBPLA(未用到index的$or),

COUNTSCAN(不使用index进行count)
当totalDocsExamined 文档扫描个数远远大于nReturned返回个数时,可以考虑使用索引。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值