数据表的物理实现
冲突的目标(最核心的特点:读写冲突)
- 并发用户数很大的系统
- 尽量以紧凑的方式存储数据(有助于查询)
- 尽量将数据分散存储(有助于存储,并发写入)
- 没有并发的修改密集型(change-heavy)
- 查询数据要快
- 数据更新也要快
- 这是一个冲突的目标
- DBMS所处理的基本单元(页、块)通常不可分割
- 在系统工程师眼里一切都很完美的时候,也可能存在一定的问题
- 如果想要优化,就必须得处理数据库引擎所访问的页和块的数量。
- 努力的方向:
- 努力使每一页的数据的密度更高(将一个检索所处理的结果尽可能的聚集在一起)
数据密集的时候方便修改,数据分散的时候方便修改、并发
在关系型数据库之中,不可能有一个技术同时对读和写都友好
页模式
- 链表模式的目的是优化查询效率
- 页不仅可以通过“目录页”查找到在哪,还有前后的指针指向前一张、后一张的页(将前后的页、块像链表一样联系在一起),方便做扫描/查找
- 目录页本质也是页,普通页中存的数据是项目数据,而目录页中存的数据是普通页的地址。
- 对于DBMS引擎来说,会自动为每一个数据块预留一小块空间
- 大约每一页只会使用大约70%的空间;超过这个空间的阀值的时候DBMS就默认这个块(页)已经存满了。
把索引当成数据仓库(IOT)
- 当索引中增加额外的字段(一个或多个,它们本身与实际搜索条件无关,但包含查询所需要的数据),能够提高某个频繁运行的查询的速度。
- 尽量在索引中多存储数据的极限是?–允许在逐渐索引中存储表中所有数据,表就是索引。
- Oracle:“索引组织表(IOT)”:所有的数据都存储在索引中,甚至不需要基本表。IOT本身是一个顺序文件。
- 对数据的宽表插入和索引是长字符串的情形非常不友好。
- Oracle:“索引组织表(IOT)”:所有的数据都存储在索引中,甚至不需要基本表。IOT本身是一个顺序文件。
记录强制排序(IOT的优缺点)
-
IOT最大的优点:记录是排序的,查询效率非常的高
- 所有基于时间进行的排序,这样做会很好(使用聚簇索引,就是以某一个属性来决定某条记录在表中的顺序)
-
使用聚簇索引之后,插入效率降低一倍;然而查询效率大幅提高
-
表变成了树状结构
-
“层次型数据库”式的数据组织结构
数据自动分组
分区
- 是一种数据分组方式
- 是最常用的提高并发性和并行性的一种策略
- 从而增强系统架构的可伸缩性
- 思想:
- 将一个大型的表,在物理上分成多个小型的表,但是借助于DBMS引擎,逻辑上依旧是一张完整的表
分区技术最早是用来进行高效管理的技术。
从前数据库拷贝是很慢的。比如一个数据库整体拷贝下来需要60min,如果在第59min的节点上出现了故障,它会直接回滚;前59min的工作可能就直接浪费掉了;
假如你把这个数据库分成10个区,拷贝操作就变成了对这10个区的顺序拷贝;每个区拷贝起来也就6分钟;如果中途再出现异常,顶多也就浪费6分钟,就从断了的节点重新开始操作就行了
数据库管理的效率就大幅提升了。
循环分区(从物理角度出发的数据分区,不考虑数据逻辑)
-
一般把分区设置在各个磁盘的存储区域中间,甚至一个分区就是一个设备。这样一个表可能会存储在一个或多个分区上。插入数据的时候,数据会按照某种方式循环加载在各个分区上,以保障插入操作的磁盘IO操作的平衡。
-
循环分区:不受数据影响的内部机制
-
分区定义为各个磁盘的存储区域
-
可以看作是随意散布数据的机制(不是根据逻辑数据的相关性来存储数据的)
-
保持更改带来的磁盘IO操作的平衡
- 循环分区对于并发的随机存储很有帮助(数据越分散,越适合并发工作)
数据驱动分区(根数据本身的逻辑有密切的联系)
社交网络数据的分区:按照时间来分区
将近3个月内的数据组织成一张表,6个月前-3个月前的数据组织成一张表,以此类推……
那么如果需要读取近一年的数据,只要连续union4张表就行了
-
核心在于“分区键(partitioned key)”,也就是分区的时候根据一个或者多个字段的值来决定这条数据应该被分在哪个分区之中。这样导致,不同的分区跟记录中间的一条或者多条数据就产生了强的/弱的联系。
-
根据一个或者多个字段中的值来定义分区
- 一般叫分区视图(partitioned view),而Mysql称为(merge table)
-
分区的实现方式
-
哈希分区
- 对分区键进行hash运算,根据运算结果进行分区
- 能够保证根据分区键可以快速的找到记录,但是对于范围的检索没有任何帮助;更接近于循环分区,只是为了做负载均衡使用的,可以提高并发能力
- 以数据值本身为分区的基础
-
范围分区
- 根据连续数据的范围进行分区
- 非常适合处理历史数据
-
列表分区
- 是一种最具手工风格的分区方案,适合定制某种特殊的解决方案
- 比如一张表有10个字段,我们把每2个字段放在一个分区,这样这张表就分成了5个分区。这就叫列表分区
- 如果一个表很大,我们的查询通常只涉及某几个字段;或者是某几个字段通常一起查询,这时候就能使用列表分区
- 有个问题:会造成主键的冗余存储,浪费空间(每一个分区都要存储一次主键,保持数据的一致性、完整性)
-
分区是可以嵌套的(套娃分区,父级分区使用A方案,子级分区使用B方案)
-
分区利弊
- 没有银弹。根据具体的查询/操作场景,有利有弊。
- 针对主要矛盾进行技术选型。
分区与数据分布
- 表非常大,且希望避免并发写入数据的冲突未必一定要用分区。
- 如果希望使用分区,那么当数据按分区键均匀分布的时候,分区的收益是最大的。
数据分区的最佳方法
- 整体改善业务处理的操作,才是选择非缺省的存储选项的目标,才是重中之重。
- 更新分区键会引起移动数据,似乎应该避免这么做
- 例如实现服务队列
- 按请求类型分区:进行的等待降低
- 按照状态分区:轮询的开销降低
- 取决于:服务器进程的数量、轮询频率、数据的相对流量、各类型请求的处理时间、已经完成请求的移除频率
- 对表分区有很多方法,显而易见的分区未必有效,一定要整体考虑
小结
- 除了堆文件之外的任何存储方法,都会带来复杂性
- 除了单库单表之外任何的存储方法,都会带来复杂性
- 选错存储方式会带来大幅度的性能降低。
- 设计非常重要,但是任何设计都有时效性
- 看重测试。