基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
说明
MYSQL 数据库表存储模型也是 IOT,Oracle 数据库则不是,建议从 Oracle 数据库迁移过来的表将主键改为唯一索引以实现和 Oracle 表存储近似的效果(比如下述分区表,Oracle 堆表不要求主键必须包含分区键)。
更新时间:2026-07-28
数据库表是数据库中组织和存储数据的一种结构化方法。遵循数据库开发规范设计合适的数据库表能够为数据提供良好的管理和处理方式,确保数据的安全性和有效性,提高数据的利用价值。
本文将主要介绍数据库表的命名规范和结构设计的最佳实践。
在设计数据库表时,采用清晰准确的命名规范至关重要。合理的命名方式不仅有助于提高代码可读性,还能确保数据的结构统一性和可维护性。
test 来表示测试表。account_user。account_user_00。account_user_2201。tmp_account_tbluser_20220224。bak_account_tbluser_20220224。name。task_num、create_date、station_desc、task_id。遵循业务性能:表结构设计不应仅依赖三大范式,而应考虑业务的性能需求,适当进行数据冗余以降低表的关联度,提升性能。冗余字段应满足以下条件:
设定主键:应为每张表设定主键,建议使用业务字段作为主键,或设定联合主键,避免使用自增列。
OceanBase 数据库的表存储模型为索引聚集表模型(IOT),如果用户未指定主键,系统会自动生成一个隐藏主键。
MYSQL 数据库表存储模型也是 IOT,Oracle 数据库则不是,建议从 Oracle 数据库迁移过来的表将主键改为唯一索引以实现和 Oracle 表存储近似的效果(比如下述分区表,Oracle 堆表不要求主键必须包含分区键)。
字段设置:每张表需具备 gmt_create 和 gmt_modified 字段,并赋予适当数据类型。
gmt_create,gmt_modified 的类型选择 DATE (精确到秒)或 TIMESTAMP WITH TIME ZONE(精确到微秒,且带当前时区信息),可以使用 SYSDATE 或 SYSTIMESTAMP 函数。
注释属性:表、字段需包含 COMMENT 属性,确保其他开发人员更好地理解数据结构和含义。
字段约束:表中所有字段应建议设置为 NOT NULL,而业务需求可自定义 DEFAULT 值。
字段一致性:多表中相同列的定义必须一致,JOIN 的关联字段类型应保持一致,避免隐式类型转换。
避免复杂类型:不推荐使用 BLOB 或 JSON 类型数据。
表示是否字段:推荐使用 unsigned tinyint 数据类型表示是/否的概念,1 表示是,0 表示否。
is_deleted,1 表示删除,0 表示未删除。如果修改字段含义或对字段表示的状态追加时,建议及时更新字段注释。
关于分区表创建时的注意事项。
如果数据量很大并且访问比较集中时,可以在创建表时使用分区表。
分区表约束注意事项。
建分区表时,表上的每一个主键、唯一键所对应的字段里都必须至少有一个字段包含在表的分区键字段中。
分区表中的全局唯一性建议能通过主键实现的都通过主键实现。
分区表的唯一索引必须包含表分区的拆分键。
关于分区策略,推荐从表的实际用途和应用场景方面进行设计。
实际用途:历史表,流水表。
应用场景:存在明显访问热点的表。
关于分区键的选择,使用分区表时要选择合适的拆分键以及拆分策略。这里仅做选择分区类型的基本推荐,更详细的内容请参见 创建和管理分区表。
HASH 分区:选择区分度较大、在查询条件中出现频率最高的字段作为 HASH 分区的分区键。
RANGE 和 LIST 分区:根据业务规则选择合适的字段作为分区键,但分区数量不宜过少。示例:如果是日志类型的大表,根据时间类型的列做 RANGE 分区。
RANGE 分区:最后一列不能是 MAXVALUE。
关于分区的使用限制。
HASH 分区下,不适合基于分区字段进行范围查询。
分区数建议:
需要根据数据的特性和需求来设计合适的字段,选择合适的数据类型和约束条件,确保数据的准确性和完整性。
数值型字段。
推荐使用 BIGINT 类型替代 INT、SMALLINT 等整型类型,防止以后范围超限。
字符型字段。
所有动态字符串建议全部使用 VARCHAR(N) 类型。
仅仅只有单字符的字段使用 CHAR(1)。表达是与否概念的字段,建议使用 CHAR(1) 类型以节省空间(1 代表 TRUE,0 代表 FALSE),值的内容要统一,所有应用值要统一,例如:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。
NUMBER(1) 也可以表达是与否的概念,但占用的空间更大些。
列的类型禁止使用 NVARCHAR、NCLOB 等类型。
字符数据类型的列可以存储所有字母数字值,但是 NUMBER 数据类型的列只能存储数字值。
日期时间字段。
有时间精度要求的业务,可以使用 DATETIME(6)。
对精度没要求的,设置为 DATETIME 即可。
如果将来有国际化需求,建议使用 TIMESTAMP。
不推荐使用字符作为时间字段的数据类型,在使用的时候容易造成隐式类型转换
数据字段的选择推荐。
特别是在大表上(百万级),推荐如下使用方法:
业务内各表时间字段务必统一,推荐使用 DATE 类型,对于精度较高的业务可以使用 TIMESTAMP 类型。
IP 所在表如果是大表,推荐使用 NUMBER 数值类型存储,可节省存储空间。前端进行转换。使用数值范围大小跟网段数据保持一致。
根据业务需要,IPv4 和 IPv6 也可以分字段存储,采用 VARCHAR(N) 存储。
数值型字段
推荐使用 NUMBER 类型存储。当 NUMBER 存储变长、十进制精度的定点数时,写法为NUMBER(p,s);当 NUMBER 存储浮点数时,写法为 NUMBER。
小数类型的字段推荐使用 DECIMAL 不推荐使用 BINARY_FLOAT 和 BINARY_DOUBLE,BINARY_FLOAT 和 BINARY_DOUBLE 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。
隐式类型转换时的优先级
BINARY_DOUBLE 的优先级最高,其次是 BINARY_FLOAT,最后是 NUMBER。
数值字段的取值范围
| 类型 | 取值范围 | 长度(字节数) |
|---|---|---|
| NUMBER | 1.0 E-130F ~ 1.0 E +126 F(不包括1.0 E +126 F) | 4~40 |
| BINARY_FLOAT | 1.17549E-38F ~ 3.40282E+38F | 4 |
| BINARY_DOUBLE | 2.22507485850720E-308 ~ 1.79769313486231E+308 | 8 |
字符型字段。
推荐使用 VARCHAR2。
比较 VARCHAR2 类型时,按照非填充空格的模式进行比较;而比较 CHAR 类型时,按照填充空格的模式比较。
日期时间字段。
TIMESTAMP WITH TIME ZONE 和 TIMESTAMP WITH LOCAL TIME ZONE 两个类型是感知时区的,请注意时区差。
不推荐使用字符作为时间字段的数据类型,在使用的时候容易造成隐式类型转换。
自增列字段必须使用 BIGINT 类型,禁止使用 INT 类型,以防止存储溢出。
禁止使用外键自引用和级联删除更新的表字段约束定义,以避免重复删除的问题。
尽量避免使用枚举列类型:ENUM('x','y','z') 应使用字符串类型替代。
如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。
字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况。冗余字段应遵循:
不是频繁修改的字段。
不是超长字段。
发生隐式类型转换时,数值类型的优先级低于时间类型,高于字符和所有其他数据类型。
合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
无符号值可以避免误存负数,且扩大了表示范围,不同的数值范围推荐不同的数据类型,示例如下:
| 对象 | 年龄区间 | 类型 | 表示范围 |
|---|---|---|---|
| 人 | 150 岁之内 | unsigned tinyint | 无符号值:0 到 255。 |
| 龟 | 数百岁 | unsigned smallint | 无符号值:0 到 65535。 |
| 恐龙化石 | 约数千万年 | unsigned int | 无符号值:0 到约 43亿。 |
| 太阳 | 约 50 亿年 | unsigned bigint | 无符号值:0 到约 10的 19 次方。 |