MongoDB 索引概念
术语
-
Covered Query/FETCH——查询覆盖/抓取
如果所有需要的字段都在索引中,不需要额外的字段,就可以不再需要从数据页加载数据,这就是查询覆盖。
db.human.createlndex(ffirstName:1,lastName:1 gender:1,age:1})
-
IXSCAN/COLLSCAN——索引扫描/集合扫描
- ixscan = index scan 索引扫描
- coolscan 集合扫描
-
Big O Notation-时间复杂度
-
Query Shape——查询的形状
查询用到了哪些字段
不同的字段,对索引是有影响的
-
Index Prefix——索引前缀
db.human.createIndex({firstName:1,lastName:1,gender:1,age:1}) 以上索引的全部前缀包括: {firstName:1} {firstName:1,lastName:1} {firstName:1,lastName:1,gender:1} # 所有索引前缀都可以被该索引覆盖,没有必要针对这些查询建立额外的索引
-
Selectivity——过滤性
查询条件使用的字段返回结果,越精确、结果集越小、越好。
索引树结构
索引背后是B-树。要正确使用索引,必须先了解B-树的工作原理。
B-树:基于B树,但是子节点数量可以超过2个
数据结构与算法复习
由于B树/B-树的工作过程过于复杂,但本质上它是一个有序的数据结构。我们用数组来理解它。假设索引为{a:1}(a升序):
索引执行计划
假设集合有两个索引
1.{city:1}
2.{last_name:1}
查询:
db.members.find({city:"LA",last_name:"parker"])
Mongodb中所谓的执行计划,更多的是选择哪个索引
评估执行计划的方式:用几个线程同时跑几个索引,看哪个索引能够最快返回想要的结果。
得出结果后,会把这个执行计划保存(缓存)起来,下次继续使用
explain()
--写入10000条文档
for(var i=1;i<100000;i++)
db.col.insert({name:i,age:i,date:new Date()})
--查询
db.col.find({name:1111}).explain(true)
执行计划中需要关注的内容:
"nReturned":1, # 返回的数据行
"execution TimeMillis":58, # 执行多少时间
"totalKeysExamined":0, # 扫描多少个索引项
"totalDocsExamined":99999, # 扫描多少个文档
"stage":"COLLSCAN", # 查看存储扫描的类型,是ixscan,collscan还是其他类型
"docsExamined":99999
# 扫描99999个文档,返回1条数据,耗时58秒,这个执行计划是非常糟糕的
"nReturned":1, # 返回的数据行
"execution TimeMillis":3, # 执行多少时间
"totalKeysExamined":1, # 扫描1个索引项
"totalDocsExamined":1, # 扫描1个文档
"stage":"IXSCAN", # 查看存储扫描的类型,是ixscan,collscan还是其他类型
# 扫描1个索引项,扫描1个文档,返回1个结果,耗时3秒。这是最理想状态,完全命中索引