文件格式
对开发者来说,内存的访问是透明的。但磁盘访问需要通过系统调用实现。需要自己设计数据结构。
字符串与变长数据
字符串可以表示成size+size个字节
物理组织
文件拆成相同大小的页、单个块或者连续块。
相同大小的页是为了简化读取和写入访问。
表结构
数据库的表结构一般是固定的,指定了字段的数量、顺序和类型。对于变长内容,会在固定字段区先存长度,再在之后的变长字段区存具体内容。
页结构
我们需要满足:
- 最小开销的变长存储需求
- 回收已删除记录的空间
- 引用页中的记录,无论它在哪
PostgreSQL等数据库采用分槽页,结构为:
- 从正向,包括header和若干个pointers,指向页内的数据项。
- 从反向,包括所有的记录cells,被pointers指向。
pointers从前往后堆叠,cells从后往前堆叠,直到二者相遇(一般会在中间留一定空间),即为页满。
数据分组
分区
将数据分散到不同的地方,提高并发性和并行性,从而增强系统架构的可伸缩性。
狭义来说,将一张表的数据分为多个区块,在逻辑上看只是一张表。
分区方式
哈希分区
对某个participation key进行哈希处理,根据哈希值分到不同的区。好处是均匀分布,和业务逻辑可能无关。
范围分区
根据participation key的值所在的范围进行分区。最常用的是按照时间分区,因为时间往往是不被修改的分区。
列表分区
把某些字段放到别的分区中(垂直拆分)
并发能力
分区和将数据聚集,利于高速检索,或是将并发分散,避免访问过于集中的问题。
数据分布在不同的文件,磁盘IO性能提高。
读写锁影响的数据量变小。
索引建立变小。
分区问题
大数据量和高并发下:
- 如果SQL不走分区键,很容易造成全表锁
- 难以实现关联查询
- 黑盒实现,不可控
分表
将一张表按一定的规则分解成N个剧院独立存储空间的实体表。
分库
全局ID生成
自动增长列
数据库自带功能,性能不错。在单库单表没问题,但分库分表需要手动规划(自增偏移+步长;全局ID映射表Redis)
UUID
简单,全球唯一。但存储和传输空间大,无序,性能欠佳
COMB
GUID+时间(6B)
Snowflake
分布式ID生成算法。各个节点无需协调,按时间大致有序,且各个集群节点不重复