本文共 3168 字,大约阅读时间需要 10 分钟。
1.第一个问题为什么没有选用Hash structure?
这个疑问应该是很多人都回想到的,因为如果用Hash表来做索引表是什么样的呢,优点是查询速度更快了,试想一下是不是,我们可以把每一行数据的地址都记录在索引表里面阿,查询的时候只要把hash索引表load内存,在冲突比较少的情况下查一次就可以确定该数据的位置了,时间复杂度是O(1),确实非常快的,熟悉计算机组成原理的同学应该非常清楚 hash索引在cache,虚存以及文件系统的设计中有大量的应用,其最大优势就是查询速度快,明显的空间换时间。 那它的缺点当然也是非常突出的,很简单如果你的数据库表数据量非常大那么想当然的索引表也非非常之大,这对于内存的利用率来说还是不好的,Hash 表无法当作数据库索引还有一个致命缺点就是,它无法进行范围的查询,hash函数的映射只是支持单值查询,如果selct * from use where age>12 这样的查询Hash表是无法实现的,当然mongodb支持创建Hash索引,后面我还会讲到。2.为什么没有选用BST(平衡二叉树)?BST 和Btree有很多类似,我们应该更熟悉BST,有序并且平衡,,但是当数据量比较大时,Btree将更加的扁平,高度更低,查询速度更快当我们为mongodb插入文档时,如果不指定_id,mongodb会自动生成id字段作为当前文档的唯一标识,和mysql是一样的,也就是说每一个文档都会有自己唯一的id mongodb会利用id来建立Btree主索引,这是默认建立的单字段索引,比如我们在person文档的age字段上建立索引,语句如下,,和之前所讲的一样,利用age字段为索引结点建立age索引表,叶结点存储主索引的值,查询过程是,通过age找到对应id,再通过id主索引找对对应的文档,,这里的参数可以指定索引的排序,1 为升序 -1为降序,然后我们看复合索引,既是在两个或是两个以上的字段建立联合索引,原理是一样的,联合age和name两个字段组织索引结点生成索引表,叶结点还是指向主索引表,也就是说,不管ji不管jianl不管建立多少索引,查询时最终还是会指向主索引表去查询文档,当然也有例外,比如覆盖索引我们后面会提到索引性能的分析
索引的建立对于数据库性能有什么影响? 建立索引有没有什么原则?
我们了解了索引的原理之后知道,查询的时候,如果查询条件不依赖PK,如果不建立索引就会引发全表扫描,如果数据量比较大时,全表扫描根本不可行,建立索引可以直接加快检索速度,IO 也呈指数即下降,那sh那是不是索引建的越多就愈好尼,也不尽然,因为查询期间索引表需要load到内存中,索引也不是越多越好,数据量比较大时,索引也会占去相当一本分内存,,而且索引应该建立在一些不经常更新并且数据重复量比较少的字段上,如果这个字经常更新,其对应的索引也需要更新,这个消耗比较高,还有就是如果这个字段的数据在数据库的重复率较高的话,建立索引的意义就没有那么大了,比如查找age=20的结果非常多,这样的效率跟全表扫描不相上下,,还有就是有时候复合索引建立,如果我们要在age和name上建立索引,只需建立两个字段的复合索引,复合索引表中结点是有两个字段组成,不用单个在两个字段上都建立索引,便可以实现高效查询。OK多说无益为了证明我的观点正确我还是要做一点实验的,我会借助mongodb自带的explain 函数来证明我前面的关键
这个查询是没有在age字段建立索引之前发起的查询,explain函数可以监控查询过程,是一个非常好用的函数,可以看到 “COLLSCAN” 立即明白这个查询过程是全表扫面,,collection scanCollection就是mongodb的一个表的单位,ok 然后我建立索引以后,再查一次看看有什么变化能看出 扫描端倪吗,我们看内层的stage:INXSCAN index scan 使用了索引扫描,,,外层stage:Fetch 大家应该可以猜得到了,这里应该是去查主索引了没错了 。 ok 我觉得索引应该已经讲得非常明白了,如果有什么不理解可以再去baidu看看。转载地址:http://xgexa.baihongyu.com/