数据库存储方法

来源:互联网 发布:网上上课的软件 编辑:程序博客网 时间:2024/05/29 10:03

在数据库中,有两种数据存放方法:


1、:数据按照向后插入的方法,一直堆积在文件末尾,使用索引结构访问数据时,将在索引中得到数据指针,然后获取数据,当有数据删除时,将其从对应位置删除,对于频繁更新的堆表,需要定期进行优化,使用堆表,会导致数据顺序访问原则被打破(在DBMS中做了访问优化,性能得到部分提升),由于没有填充因子,在相同压缩算法下,空间能得到很大的节省,堆表很适合于顺序范围访问,如数据仓库等业务场景。

2、索引组织:一般索引组织表使用B+作为构造方法,整个结构如同一个倒挂的数(从数据访问流来看),路由信息存放在树枝上,所有的数据存放在叶子节点,通过双向指针将所有叶子根据顺序方式串联起来,由于时空访问局限特性,这能很大提升数据性能,DBMS根据访问存取路径访问及构造数据,访问路径深度直接影响了性能,一般建议访问路径控制在4以内(小于或等于3),原因由于访问多层路径需要消耗更高的代价及维护索引树代价越来越昂贵。

我们常见的Innodb、MySQL Cluster等都是索引组织表、MyISAM为堆表,MongoDB的组织结构为堆。

拥有ACID属性的数据库拥有索引维护功能,MyISAM存储引擎以及MongoDB由于是堆组织结构,且没有ACID的控制,会导致元数据与索引不一致的问题,直接导致数据存取失效,造成数据不一致,但由于没有ACID的要求,更新速度将得到很大地提升,MyISAM存储引擎需要定期进行一致性check,正是因为不具有ACID属性,MyISAM存储引擎需要为数据更新锁定表,造成大并发下更新的低性能。


MongoDB复制集架构:

MongoDB提供了和MySQL Cluster类似的架构,在configure server、mongos、mongo中,包含:

configure server:提供集群元数据,其中包含基本信息、每个replica set、trunk及trunk大小等信息。

mongos:数据访问路由、查询优化、数据merge、sort、裁剪等功能,请求推送等。

mongo+replica set:数据存取。

MongoDB Shard架构:


MongoDB在构建集合时,需要提供数据分片规则,该规则将被记录在MongoDB中,查询请求mongos发起请求,mongos根据存取路径在Replica中访问数据。由于MongoDB为用户提供了一个选择性,将数据如何进行切片,在对用户访问透明的情况下,快速存取数据。

MongoDB面临的问题:

以非分片规则访问数据时(索引可以建立在各个分片),将导致所有Mongo簇节点全扫描(可以通过多份冗余拷贝并进行不同的分片规则实现,这也是当前数据分片应用常用的手段)。当新增数据簇时,将导致所有数据节点重构,直接影响性能。


MongoDB分片片键的选择:

MongoDB的分片机制能够将数据库划分到多个服务器,通常在生产环境中可以将数据集划分到多个副本集中。为了实现分片,必须向MongoDB指定使用哪个索引作为片键,然后MongoDB会根据你的设置将数据划分到有相同片键的数据块(Chunk)中。而后这些数据块将根据片键的大致顺序分散到副本集中。(即分片之后数据的存放位置依赖于片键,所以对于分片key的选择直接决定了集群中数据分布是否均衡、集群性能是否合理)

选择好片键的要素:

1、读和写的分布:如果总是朝一台机器写,那么这台机器将会成为写瓶颈,则你的集群的写性能将会降低。因此不应该使用单调递增的_id或时间戳作为片键,这样将会导致你一直往最后一个副本集中添加数据。类似的对于读操作,通过副本集将请求划分开能够使你的工作数据集大小随着分片数线性扩展。这样就能将负载压力均分到各机器的内存和磁盘之上。

2、数据块的大小:MongoDB能够将大的数据块划分成更小的,但这种情况仅仅在片键不同的情况下发生。如果有大量的数据文档都使用了相同的片键,那么相应也会得到巨大的数据块。出现巨大的数据块不仅仅因为它会导致数据的不平均分布,而且还会在当它的大小超过某个值时,不能够在分片之间移动它。

3、每个查询命中的分片数目:即保证大部分的查询请求都能够命中尽可能少的分片。对于一个查询请求来说,其延迟直接取决于最慢的那个命中服务器的延迟;所以你的命中的分片越少,则理论上来说查询将会越快。


选择好的片键:

1、Hashed id:使用数据文档_id的哈希作为片键,这样能够使读和写都能够平均分布,并且它能够保证每个文档都有不同的片键所以数据块能够很精细。但是这样对多个文档的查询必将命中所有的分片。

2、多租户混合索引(Multi-tenant compound index):

db.doc.createIndex({projectId:1,_id:1})
使用projectId作为片键,它会导致巨大块的产生,因此还需要引入_id来将大project打散到多个块中。这些打散的块仍然是索引连续的,所以仍然会分布在用一个分片上。

原创粉丝点击