平时总结的自己做开发时设计 Schema 的一些原则,大家有什么这方面的分享么? 这里放不下太多内容,贴一些主要的
- 表尽量不要前缀 - 清晰明了
- MySQL 额外考虑
- PG 支持 Schema 隔离 - 避免直接使用 public schema
- 字段尽量不要缩写
- 尽量不要用 拼音
- 做国内环境除外 - 例如:政企数据无法很好翻译
- 维护开发字典 - 例如 开发用词字典
- 尽量 不要 用自增长 ID
- 容易被遍历
- 面向用户的可以 增加额外的 自增长 编号/序号
- 使用 有序的 随机主键 - ULID, UUID
- 建议主键增加 type tag
- PostgreSQL
- 尽量用 text, bigint, jsonb, bool
- 看情况用 array - array 能简化不少需要 join 表的场景 - 例如
tags text[] - 避免 varchar(n) 限定长度
- 业务层控制 validation
- 通过 check 验证
| column | for |
|---|---|
| id | 主键 - ULID, tagged ID |
| sid | 租户维度单调递增 - 用户友好 |
| uid | UUID |
| tid | 租户 ID |
| eid | 用于导入数据关联 - tid+eid 唯一 |
| cid | 外部系统租户 ID - Colocate ID/Corp ID - tid+cid+rid 唯一 |
| rid | 外部系统资源 ID - Ref ID/Relative ID |
| created_at | |
| updated_at | |
| deleted_at | |
| version | 基于版本的乐观锁 |
| metadata | 补充数据 |
| attributes | 使用端自定义数据 - 客户端 读写 |
| properties | 服务端自定义数据 - 客户端 只读 |
| extensions | 内部扩展数据 - 客户端 不可见 |
| owner_id | 所有者 |
| owner_type | User, Team, Department, Organization |
| owner_user_id | case owner_type when 'User' then owner_id end |
| owner_team_id | case owner_type when 'Team' then owner_id end |
| entity_id | 关联任意实体 |
| entity_type | |
| created_by_id | |
| updated_by_id | /tr> |
| deleted_by_id | |
| state | 状态 - 面向系统,不可自定义 |
| status | 业务状态、阶段、原因、细节 - 可自定义 |
- eid
- 同质系统导入外建关联 - 例如: SaaS <-> 现存内部系统
- 也可能会导出再导入
- cid & rid
- 非同质系统 - 例如: 服务商、平台
- -> sourceType+sourceId
- -> vendorType+vendorId
create table tpl_res ( -- 基础 id text not null default gen_ulid(), tid bigint not null default current_tenant_id(), -- 租户 uid uuid not null default gen_random_uuid(), sid bigint not null default (next_res_sid('tpl_pri_resources')), eid text null , -- 用于导入数据关联 created_at timestamptz not null default current_timestamp, updated_at timestamptz not null default current_timestamp, deleted_at timestamptz, -- auditor 信息 created_by_id text default current_setting('app.user.id'), updated_by_id text default current_setting('app.user.id'), deleted_by_id text, -- 按需附加任意层面的数据 -- 例如: attributes 允许客户端修改, properties 不允许客户端修改, extensions 客户端不可见 extensions jsonb, properties jsonb, attributes jsonb, -- 业务 owner 信息 owner_id text, owner_type text, owner_uid uuid, owner_id text, owner_type text, -- User, Team, Department owner_user_id text generated always as ( case owner_type when 'User' then owner_id end ) stored, owner_team_id text generated always as ( case owner_type when 'Team' then owner_id end ) stored, owner_department_id text, primary key (tid, id), unique (tid, sid), unique (tid, uid) ); FAQ
created_at vs create_time
- created_at,
*_at- 语义 准确
- 与
created_by_id形式上类似 - 使用: Spring, Gorm 默认
- 面向 系统
- create_time,
*_time- 使用: AIP
- 面向 用户, 业务
扩展 {#extension}
- extensions
- 内部使用
- properties
- 服务端使用,前端可见
- attributes
- 前端使用,服务端可见
- metadata
- 对数据内容的补充说明
- raw
- 外部导入原始数据
- 也可以记录到 metadata, properties.raw, extensions.raw
单数还是复数表名 {#plural}
推荐单数形式。 部分关键词使用复数: users, groups 。
- 复数
- 大多框架默认
- 语义上更准确
- 逻辑上更复杂
- 单数
- 代码层面更好统一
- 但部分单数形式可能需要 quote
- user 也可以用
app_user之类的作为区分
- 参考
尽量使用外键 {#fk}
- 能一定程度提升查询性能
- 增加部分 插入 和 更新 成本
- 确保业务逻辑准确
- 非强业务看情况
