索引性能的分析
索引的建立对于数据库性能有什么影响? 建立索引有没有什么原则?
我们了解了索引的原理之后知道,查询的时候,如果查询条件不依赖主见,如果不建立索引就会引发全表扫描,如果数据量比较大时,全表扫描根本不可行,建立索引可以直接加快检索速度,IO 也呈指数即下降,那sh那是不是索引建的越多就愈好尼,也不尽然,因为查询期间索引表需要load到内存中,索引也不是越多越好,数据量比较大时,索引也会占去相当一本分内存,,而且索引应该建立在一些不经常更新并且数据重复量比较少的字段上,如果这个字经常更新,其对应的索引也需要更新,这个消耗比较高,还有就是如果这个字段在数据库的cho就是如果这个字段的数据在数据库的重复率较高的话,建立索引的意义就没有那么大了,比如查找age=20的结果非常多,这样的效率跟全表扫描不相上下,,还有就是有时候复合索引建立,如果我们要在age和name上建立索引,只需建立两个字段的复合索引,复合索引表中结点是有两个字段组成,不用单个在两个字段上都建立索引,便可以实现高效chaxu便可以实现高效查询,
性能优化问题:
现在假设有book和user两个集合,book和user的关系是一对多的关系,在mongodb,我们用嵌套的方式来biaosh嵌套的方式来表示这种关系,这样查询起来就非常方便,不用关联,,但是如果业务需求需要经常use但是如果业务需求需要经常更新user集合的age字段,这会产生怎么样的问题尼,,
不仅要修改user集合的age字段,也要去book扫描所有嵌套的文档将age属性改掉,这样的话,更新的效率是非常低的
如果 age对于book表不是必须的,我们可以在book的嵌套字段里面把age剔出,这样只需要更新user集合,往往查询效率和写的效率是冲突的,如何处理好这种关联关系很值得我们去思考和学习,所以说嵌套文档的处理适合那些数据比较稳定持久的字段,如果这个字段需要经常更新,就需要去考虑如何设计好这种关系结构。
填充因子的问题
我们知道mongodb数据的存储结构是顺序表的形式存储在磁盘上,也就是说每一个文档在物理位置上是相邻的,现在我们可以思考一个问题,如果说现存的某一个文档的字段值发生了变化,占用的存储空间增大,,这时原来存储这个字段的扇区空间b空间不够用了,必然导致这个文档往后所有的文档都向后移动,了解顺序表的都知道,顺序表最大的缺点jiush顺序表最大的缺点就是元素的移动,这种操作的性能消耗是巨大的,所以在存储文档时就应该为文档预留相应的冗余空间,防止文档的大量移动,,我们这里提到的填充因子就是为文档扩展提供的预留空间,
这里有两种解决方案
1增加初始分配空间。在集合的属性中包含一个 usePowerOf2Sizes 属性,当这个选项为true时,系统会将后续插入的文档,初始空间都分配为2的N次方。这种分配机制适用于一个数据会频繁变更的集合使用,他会给每个文档留有更大的空间,但因此空间的分配不会像原来那样高效,如果你的集合在更新时不会频繁的出现移动现象,这种分配方式会导致写入速度相对变慢。
2.我们可以利用数据强行将初始分配空间扩大。
是的,这样看起来可能不太优雅…但有时却很有效!当我们对这个文档进行增长式修改时,只要将stuff字段删掉即可。当然,这个stuff字段随便你怎么起名,包括里边的填充字符当然也是可以随意添加的。
mongodb sharding
什么是分片尼 ? 我们可以去设想如果一个数据集合里面已经存在海量数据tb级别的数据,而同时又有多个线程需要访问这些数据,单台服务器肯定无法消化,mongodb采用了分布式解决方案,比如将一个集合的数据分片,chunck,然后不同的分片存贮在不同的服务器上面,当用户访问集合里面的文档时,mongodb可以根据请求条件来查找到对应数据所在的服务器然后返回数据,这样下来可以将du可以将多请求的负责分摊到各个服务器的分片上,大大提高数据库系统的吞吐量,
可以看一下sharding的结构,最上面mongos路由是就相当于路由器一样对各个数据库请求进行分发,是qingqi是请求的入口,然后通过ConfigServers查找请求数据对应所在分片,所以configserver的作用就是为路由器提供分片线索,可以理解为各个不同分片的索引表一样,可以快速查到对应分片,然后就可以去访问shard服务器了。。我们可以看到mongos路由不止一个,原因很简单,一个高可用分布式集群方案,必须保证服务时刻都可以正常高效运行,在这里在多个服务器配置同样的mongos路由,sh是为了fangzh是为了防止当前使用的路由出现问题而备用的。同样的configserver 同样需要完全相同副本分布在不同的服务器上备用,,shading也一样可以设置副本,
因为公司之前有同事已经搭建过mongodb的分片集群,也从rover系统中迁移了一些数据过来,我对已经搭建好的环境进行了一些分析
首先我们可以用config,这个默认创建的数据库来查看一些分片信息,config数据库用这些集合来记录了一些配置信息,察看shards表可以看到,我们用了5台服务器5个分片来搭建,之后也可以看到每个服务器数据库服务的端口,,通过databases这个数据库可以看到不同数据库的,zh只有pmch进行了分片,也可以看到这个数据库的zh也可以看到这个数据库的主分片是shard0002,主分片这个概念我想应该是在分片的情况下产生的,也就是说如果有一些集合不需要分片的话,那这个集合的数据就存放在主分片里面。
每一个数据库都有一个主分片
那么mongodb 是依据什么来du是依据什么来对集合数据进行分片的呢,总不能随机把sh总不能随机把数据放到不同的分片里,这样根本无法检索数据,因为根本没有规则也没有y因为根本没有规则也没有依据,mongodb用shard key 来支持分片,作为分片的依据,shard key 来自于集合中的字段,有两种分片的方式,第一种hash 通过h通过hash函数对字段进行yi函数对字段进行映射,然后cunch然后存储到对应的分片上,我们看到这这个连续的值在hush下可能会存贮与不同的分片。但是在xianxi方式但是在线形方式三个doc很有可能会ji很有可能会进入一个分片,,那么思考yixi那么思考一下在这种情况下那种分片方式好?? 如果shard key 是线形增长的,那么ranged sharding这种方式下会产生严重的问题,大家思考一下,随着新插入的shard key越来越大,sh是不是最后新插入的文档都回进入z最后yi最后一个分片中,这回造成最后一个分片过大,数据分配不均匀,造成瓶颈障碍,使得请求集中于最大的分片服务器上,这样就失去了分片的yiy这样就失去了分片的意义,所以说在特定的情况下,选择hashbji比较合适,zh这一块官网给出了用_id来做shard key 用hash方式来分片,能够有比较好的性能体现,具体生产中用那种方式还需要结合具体情况,总之原则就是避免数据聚集,目前只能研究到这