术语

  • 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秒。这是最理想状态,完全命中索引