对象设计规范
📄字数 3.8K
👁️阅读量 加载中...
在进行数据库开发时,开发人员会创建各类数据库对象,本文档旨在统一开发时对各类对象的设计原则,确保数据库具备高可维护性、高性能与高扩展性。
一、表结构设计
表是数据库开发人员最常用的对象之一,是关系型数据库的核心,其结构设计的优劣直接决定了系统的性能和稳定性。开发过程中通常会设计各种表对数据库进行操作,本节针对表结构设计提出建议。
1.1 字符集选择
正确设置表的字符集是避免出现乱码和保证数据存储正确性的基础。
- 推荐使用
UTF8
作为数据库、表、字段的统一字符集。- 原因:
UTF8
是8位Unicode转换格式,具有良好的国际兼容性,适合多语言环境。
- 原因:
- 推荐在整个数据库流程上保证统一的字符集:数据库连接->数据库实例两个层面的字符集设置保持一致,从根源上杜绝乱码问题。
1.2 主键设计
主键是表的身份标识,用于唯一确定表中的每行数据,一个良好设计的主键对于表来说十分重要。
- 强制性:关系数据库标准理论规定,每一张表都应当有一个主键。没有主键的表可能导致数据更新异常、重复的无意义数据或频繁的全表扫描,影响整体业务性能与稳定,属于设计缺陷。
- 单一性:推荐使用单一字段构成的主键,不推荐使用复合主键。复合主键创建的二级索引较为复杂、占用空间更大,并且在关联查询中很不方便。
- 无业务含义:推荐使用与业务无关的、自增的整数类型作为主键。
- 优点:
- 性能:数值型、持续递增的主键有利于索引的紧凑存储,实现高效插入。
- 稳定性:业务相关的数据可能会发生变更,使用业务数据作为主键会导致级联修改,成本极高。
- 匿名性:避免主键暴露业务信息。
- 优点:
- 类型选择:
- 对于未来数据量可能超过20亿的大型表选择
BIGINT
作为主键类型。 - 对于中小型表,使用
INTEGER
。 - 不推荐使用
GUID
或可变字符串类型作为主键,无序性会导致索引插入时产生大量的随机I/O与页分裂,严重影响写入性能。
- 对于未来数据量可能超过20亿的大型表选择
1.3 逻辑删除
为了保证数据的可追溯性和安全性,应采用逻辑删除方式代替物理删除。
- 实现方式:在表中增加一个删除标记字段,推荐使用
TINYINT
类型。 - 访问方式:推荐前台业务在查询、更新时,增加检查删除标记字段。
- 优点:
- 可恢复:误删除的数据可以快速恢复。
- 审计与分析:保留完整的数据记录,便于问题排查与数据溯源、分析。
- 保持关联:避免因主表数据物理删除而导致关联表出现数据孤岛。
1.4 表的拆分
当单表的数据量过大时,会导致查询和维护困难,此时需要考虑对表进行拆分,可分为垂直拆分与水平拆分。
垂直拆分:
- 场景:当一个表字段过多,并且包含访问频率较低的字段时。
- 方法:将表的字段按照访问频率、业务关联性等特征,拆分为一个主表与一个或多个拓展表。主表包含访问最频繁的核心字段,拓展表包含不常用的字段或大对象字段,二者通过相同主键进行关联。
- 优点:减少主表的字段数量,提高核心查询的I/O效率与缓存命中率。
水平拆分:
- 场景:当单表行数过多,即使存在索引与分区,仍然出现性能瓶颈时。
- 方法:将表中给的行数据,按照一定的规则分散到多个结构相同的表中。
- 优点:突破单表的存储与性能瓶颈,实现快速拓展。
1.5 范式与反范式策略
在进行表结构设计时,为了建立起冗余更小、结构更合理的数据库,研究人员提出数据库三大范式,其描述了数据库创建时要遵循一定的规范。
范式分级与应用
范式等级 | 含义简述 | 适用场景 |
---|---|---|
第一范式(1NF) | 每一列原子性,不可再分 | 所有表(基础) |
第二范式(2NF) | 非主属性完全依赖主键 | 事实表、数据仓库建模 |
第三范式(3NF) | 非主属性不依赖于其他非主属性 | 日常业务表设计的推荐目标 |
BCNF/更高范式 | 更严格的依赖消除 | 高度复杂的数据一致性要求、模型分析 |
通常情况下,业务表默认遵循3NF,部分情况下可降低至2NF,但至少需要保持1NF。
反范式策略
范式规定了数据库设计应当遵循的标准,然而在某些实际生产环境中,“完全范式化”虽然保证了数据的一致性与灵活性,但往往会导致系统在高并发或复杂分析场景下出现性能瓶颈,或导致复杂度大幅升高。因此,研究人员提出反范式策略,旨在避免完全范式化所带来的性能与复杂度问题。反范式策略是在性能、业务、运维的权衡下做出的工程选择。
反范式策略适用场景
高频查询/写入下的多表连接性能瓶颈
- 冗余主表部分字段至子表/汇总表,减少关键路径上的连接次数。
聚合场景
- 创建汇总表,定时与分表进行同步,维持计数、区间统计等信息,避免全表扫描。
历史快照与审计信息
- 冗余快照数据,避免因主表更新而导致历史追溯失真。
反范式策略的注意事项
- 冗余字段文档化:在表结构、字段中注释冗余字段的来源与同步方式。
- 一致性:建议使用触发器、定时作业任务保证主表与冗余字段的同步。
- 只读:冗余字段应只用于查询、聚合使用,不得作为数据来源。
- 变更风险:当主表结构或业务逻辑变更时,同步评审所有相关冗余字段。
所有表的设计都推荐包含应有的注释,并在业务改变时相应修改注释。
二、字段结构设计
字段是表的最小数据单元,良好的字段结构设计能够有效的节约存储空间,提升查询时的性能。
在字段设计中,建议遵循以下原则:
选择最恰当的数据类型:在满足业务需求的前提下,选择存储空间最小的数据类型。
- 整数:根据数值表示范围选择
TINYINT
、SMALLINT
、INTEGER
、BIGINT
,在存储空间不紧张的场景,使用BIGINT
,防止未来出现溢出。 - 字符串:使用
VARCHAR
类型,并设定一个合理的、贴近业务范围的最大长度,避免预留过多空间。 - 浮点数:应当使用
NUMERIC
类型,不推荐使用FLOAT
与DOUBLE
类型,以防出现精度丢失。 - 日期时间:使用
DATETIME
或TIMESTAMP
,避免直接使用字符串存储日期时间类型,容易造成不必要的隐式转换。
- 整数:根据数值表示范围选择
避免使用
NULL
值:除非业务逻辑明确需要表示未知状态,否则所有字段都应设置NOT NULL
或给定默认值。- 原因:
NULL
值会增加逻辑查询的复杂程度,影响索引效率。
- 原因:
一致性:在不同表中代表同一业务含义的字段,应当统一使用相同的数据类型。
注释:推荐每个字段都增加详细注释,指明业务含义、单位、数值表示范围等信息。
字段冗余:指在数据库中有意地在多个位置存储相同数据的设计策略,其主要目的是通过减少表连接操作来提升查询性能。应当遵循以下原则;
- 不是频繁修改的字段。
- 不是存储大文本的字段。
三、分区表设计
当出现数据量较大且访问数据较为集中时,推荐在创建表时使用分区表。
3.1 适用场景
- 大数据量:单表数据量>=1亿行,或单日写入>=100万行。
- 冷热分离:需要按照时间、用户、地理位置等维度快速进行数据裁剪或数据迁移。
- 合规留存:例如资金、审计等项目需要按照规定保留,且需要定期清理。
3.2 分区键设计原则
- 高命中:分区键必须是查询中使用最频繁的过滤条件,以实现分区裁剪。
- 低修改:避免使用频繁更新的字段作为分区键,会触发迁移。
- 唯一索引:分区表的唯一索引必须包含表分区的分区键。
3.3 分区类型
- RANGE分区:最常用的分区类型,适合于按时间或连续数值范围进行分区。
- LIST分区:适用于按地区、渠道等离散且固定的值进行分区。
- HASH分区:用于将数据打散到不同分区,适用于业务范围不明显但希望I/O分散的场景,选择区分度大、在查询中出现频次最高的字段作为分区键。
分区表建议定期进行维护,如创建新分区、归档或删除过期分区。
四、索引设计
索引是数据库开发过程中提升查询性能的有效手段,但滥用索引也会导致写入性能降低并占用大量存储空间等问题,本节介绍在索引设计中建议遵守的规范和原则。
4.1 设计原则
目标明确:为
WHERE
、JOIN
、ORDER BY
、GROUP BY
子句中频繁使用的字段建立索引。选择性:优先为区分度高的字段建立索引。区分度越高,索引的查询效率越高。
单列索引:
- 建议对索引字段设置
NOT NULL
属性,通常根据业务定义默认值。 - 在
JOIN
表达式中使用的字段,类型建议保持一致;在多表关联查询时,保证被关联字段上存在索引。 - 建议将输入条件进行过滤,避免因大量结果集查找而导致的搜索空间爆炸。
- 建议对索引字段设置
复合索引:
- 遵循“最左前缀”原则,将最常用、区分度最高的字段放在复合索引的最左侧。
- 对过滤表达式中频繁使用的字段添加到索引后面,形成覆盖索引,避免回表。
- 多列查询条件使用复合索引。
4.2 注意事项
- 避免重复索引,冗余的索引影响写入性能,同时占用存储空间。
- 在复合索引创建的前提下,无需再单独创建最左字段索引。
- 减少分区表全局索引的定义,全局索引的维护代价高昂,不建议过多使用。
- 当修改字段上的索引时,确认索引状态,处于有效或失效。
五、其他结构设计
对于其他的数据库对象,建议依照如下表格:
对象 / 主题 | 主要规范与最佳实践 |
---|---|
视图 (View) | 封装复杂 Join;避免视图嵌套。 |
存储过程 / 函数 | 仅限批量或强事务场景;所有脚本纳入版本控制。 |
触发器 (Trigger) | 谨慎使用,仅用于审计或自动字段填充;需注明目的与性能评估。 |
六、数据库对象限制
本章针对 XuguDB 中各类数据库对象的设计与使用,列出关键限制与边界,帮助开发与运维团队在架构层面规避兼容性、性能或运行时错误。
限制项 | 最大值/范围 |
---|---|
最大标识符长度 | 127 字节 |
最大用户口令长度 | 127 字节 |
最大路径长度 | 256 字节 |
单个字段最大长度 | 非大对象:60000 字节 大对象:2GB |
最大记录长度 | 60000 字节 |
最大字段个数(每表) | 2040 列 |
嵌套事务最大级数 | 32768 层 |
最大 X 日志记录长度 | 65536 字节 |
OBJECT、VARRAY 类型成员数量 | 65535 项 |
分区列最大数量 | 32 列 |
索引记录最大长度 | 4000 字节 |
最大字段数量(单查询) | 2047 个 |
包 ID 最大分配额度 | 1048576(≈1M) |
更多可自定义控制的对象限制请参阅系统配置章节。