# 4 数据库对象命名规则

## 4.1 表
### 4.1.1 表名规范
- 数据表名称以 TB_为前缀，命名规则为“TB_模块名_表名”。
- 模块名由特征含义的单词或缩写组成，避免使用数据库关键词。
- 命名一律为大写字母。
- 如果用来存储历史资料，命名以 HISTORY 结尾。
- 如果用来存储日志资料，命名以 LOG 结尾。
- 如果用来存储类别资料，命名以 TYPE 结尾。

### 4.1.2 表分区
- 表分区命名带有 P 字段，命名规则为“TB_模块名_表名_分区名”。
- 分区名必须有特定含义的单词或字串。
- 子分区命名：父分区名_SP_区域缩写，根据实际情况进行组合。

### 4.1.3 字段名
- 字段名全部采用英文单词，如有多个单词，则单词之间需用“_”隔开。

### 4.1.4 主键
- 主键名称以 PK_为前缀，命名规则为“PK_表名(或缩写)_XXXX”。
- XXXX 以数字或者英文字母表示，应明确表达出代表含义。
- 主键定义需要在数据库设计文档中体现出来。

### 4.1.5 外键名
- 表外键名称以 FK_为前缀，命名规则为“FK_表名(或缩写)_主表名(或缩写)_XXXX”。
- XXXX 以数字或者英文字母表示，应明确表达出代表含义。
- 外键定义需要在数据字典中体现出来。

## 4.2 索引
### 4.2.1 普通索引
- 普通索引以 IDX_为前缀，命名规则为“IDX_表名_字段名(或缩写)”。
- 若索引由多个字段组成，则命名为“IDX_表名_字段名(或缩写)1_字段名(或缩写)2_......”。
- 若索引长度超限，则命名规则为“IDX_表名_序号”。
- 每个索引名称与其对应的字段名需要在数据字典中明确体现。

### 4.2.2 主键索引
- 主键索引应与主键约束名相同，或 IDX_主键约束名。

### 4.2.3 唯一索引
- 唯一索引以 IDX_UNI_为前缀，名称规则为“IDX_UNI_表名_数字”。

### 4.2.4 外键索引
- 外键索引应与外键约束名相同，或以 IDX_外键约束名。

### 4.2.5 函数索引
- 函数索引以 IDX_FUNC_为前缀，名称规则为“IDX_FUNC_表名_数字”。

## 4.3 视图
- 视图名称以 V_为前缀，命名规则为“V_模块名_视图名”，规则与表的命名类似。

## 4.4 实体化视图
- 实体化视图名称以 MV_为前缀，命名规则为“MV_模块名_实体化视图名”，规则与表的命名类似。

## 4.5 存储过程
- 存储过程名称以 SP_为前缀，命名规则为“SP_过程名称(缩写)”，名称能表达实际含义的英文单词或缩写，多个单词需用下划线分割各个组成部分。

## 4.6 触发器
- 触发器名称以 TR_为前缀，命名规则为“TR_表名_触发器名”。

## 4.7 函数
- 函数名称以 FUN_为前缀，命名规则为“FUN_功能名称”，按业务操作命名存储过程。

## 4.8 序列
- 序列名称以 SEQ_为前缀，命名规则为“SEQ_表名_数字”。

# 5 数据库应用设计

## 5.1 数据库用户
### 5.1.1 用户权限控制原则
- 坚持最小化权限分配原则。
- 每个业务用户不得授予 DBA 角色。
- 取消系统权限时，必须征询开发者的意见。

### 5.1.2 用户及其权限规范
- 根据数据库管理、数据维护、开发、功能等方面将数据库用户分为：数据库管理员（DBA）、数据库属主（DATA OWNER）、交易用户（Transaction）、监控用户（Monitor）、其他用户（Other）。

## 5.2 数据库 schema 设计规则
- 应用设计表，不能包含于 public schema 中。
- 创建与数据库属主用户同名 schema，所有者为数据库属主用户，应用设计表全部包含于此 schema 中。
- 对于其它用户对数据库属主用户同名 schema 只有 USAGE 权限。

## 5.3 数据库分库设计
- 应用系统的业务功能和数据处理流程匹配，数据结构设计层次清晰，结合总体应用逻辑架构设计进行各子系统数据库的分库设计，最终获得数据库与应用的架构清晰、性能优化的综合要求。
- 应用系统在设计时，应根据应用特点、应用场景、单库的处理能力、单库的数据容量，确定数据库分库的数量。
- 分库规则应语义明确清晰，如按客户号、签约协议号、商家代码或业务代码等。根据指定的分库键，将数据表进行拆分，通过应用或在数据访问中间件上配置规则，实现数据路由。
- 数据库分库设计遵循如下原则：
  - 需分库的数据，原则上不能有冗余。
  - 分库的算法不能存放在所分库的任何其中一个库中。
  - 通过应用服务或数据库访问中间件支持分库访问。

## 5.4 数据库表设计规则
- 遵循应用设计规范，保证数据的完整性与正确性。
- 开发时应遵循数据模型设计要求。
- 使用统一的命名规则，数据库对象能表达出明确的含义。
- 开发时应考虑程序的优化设计。
- 表设计时不建议创建外键约束。
- 除配置信息外，业务表建议预留 3-5 个冗余字段及时间戳字段。
- 根据业务场景选择表字段个数，宽表字段个数建议不超过 200，窄表建议不超过 50。

## 5.5 数据库表分区设计
### 5.5.1 表分区的目标
- 提高访问表的性能。
- 增强表的管理和维护性。

### 5.5.2 表分区基本原则
- 依据数据模型的大小进行分区设计。
- 依据应用处理功能需求进行分区设计。
- 依据提高并行处理性能进行分区。
- 依据数据访问特性进行分区设计。
- 依据数据维护可行性、方便性需求进行分区设计。

### 5.5.3 分区表的使用
- 建议使用 PostgreSQL 自带的分区表功能。

## 5.6 数据库长连接
- 建议从应用层面解决数据库长连接耗内存的问题：间隔一段时间或处理了一定笔数的交易后主动断开数据库长连接重连；使用数据库连接池的，可在 datasource_releaseconnection()扩展下功能，定时或达到一定计数后断链重连。

## 5.7 游标的使用
- 由于游标的效率较低，如果在代码中可以通过不同的条件分支实现的逻辑，尽量不要使用游标。
- 动态游标通常都可以转化为若干个静态游标，除非必要，尽量使用静态游标代替动态游标。
- 应采用如下顺序使用游标：DECLARE 声明游标、OPEN 打开游标、操作游标、关闭游标，使用 FETCH、MOVE、UPDATE 或 DELETE 语句操作游标。
- 如果使用 UPDATE WHERE CURRENT OF 或 DELETE WHERE CURRENT OF 语句更新或删除行时，游标在定义时应定义为更新游标。更新游标应结合 SAVEPOINT 语句提供更新失败后事务回滚点。

## 5.8 查询事务
- 在 PostgreSQL，所有的 SQL 操作都在事务中，包括 SELECT 语句，在 SELECT 操作后如果长时间没有事务提交或事务回滚，就存在查询事务，查询事务过多将占有数据库服务器的资源，PostgreSQL 数据库监控软件会监控到这一现象从而引发告警。建议应用开发时，考虑查询事务，及时将事务提交或回滚。

## 5.9 批量处理、批转联处理
- 批量处理、批转联处理须避免大事务，批转联须进行并发度控制。
- 单次任务处理原则上不应超过 5000 笔。
- 单次任务调用或数据库单事务提交的明细数量，原则上不应超过 5000 笔。

## 5.10 索引设计规范
- 在 PostgreSQL 中，索引是提高查询性能的重要工具，但过多的索引会增加磁盘空间的需求，并且在数据写入时也会增加索引维护的开销。因此，应该根据实际需要合理使用索引。只有在查询频繁且对性能有显著提升的情况下才考虑创建索引。在使用过程中索引也需要定期维护和更新，当表数据发生频繁变化时，可以定期更新索引，也可以使用 VACUUM 命令进行表碎片整理，以减少索引的碎片并提高性能。对不再使用的索引可以定期检查并删除以提高查询性能。

### 5.10.1 索引主要两种形式
- 主键和唯一约束：对于主键和唯一约束，PostgreSQL 会自动创建一个唯一索引以确保数据的唯一性。
- 多列索引：PostgreSQL 支持基于多个字段的索引，即多列索引（复合索引），从而提高复杂查询的性能。默认情况下，一个多列索引最多可以使用 32 个字段。

### 5.10.2 索引设计原则
- 列名一致性：多表中的相同列应保证列名一致，数据类型也需保持一致。
- 字段大小限制：btree 索引字段不建议超过 2000 字节。如果有超过 2000 字节的字段需要建索引，建议使用函数索引（例如哈希值索引），或者使用分词索引。
- 外键索引：如果使用的 PostgreSQL 版本没有自动建立外键的索引，则需要手工为 foreign key 建立索引，否则可能影响 references 列的更新或删除性能。原则上尽量少使用或不使用外键索引。
- 避免冗余索引：不要重复创建功能相同的索引，例如已经存在的联合索引(a, b, c)就涵盖了(a)、(a, b)的功能，可降低存储和维护成本。
- 索引覆盖与更新频率：设计单个索引尽可能覆盖更多的 SQL 语句，同时对于更新频繁的表要控制索引的数量，以避免过度的维护开销，对于频繁更新的列，原则上不建议在该列建立索引，因为频繁的更新操作可能会导致索引维护成本增加甚至是索引失效，从而降低索引的效率。
- 索引数量及列的空值问题：单张表的索引数量尽量控制在 5 个以内，且确保索引列不含 NULL 值，因为 NULL 值很难用于优化查询。
- 区分度与字段顺序：选择区分度高的列建立索引，通常将用作查询条件、连接操作或排序的列作为创建索引的候选列。在组合索引中将区分度最高的字段放在前面，以提高效率。部分索引和在线索引：根据业务场景需要可建立包含满足特定条件的部分索引设定用于优化特定条件下的查询性能，对于生产环境在不锁定写入的情况下构建索引，可以采用在线创建索引的方式构建。

## 5.11 数据库和表的统计信息定期收集
- PostgreSQL 从低版本采用 pg_upgrade 方式升级到高版本后，应收集数据库统计信息。
- 数据量变化频繁的表，建议定期进行表的统计信息收集，建议增加应用系统的日终任务进行表的统计信息收集。

## 5.12 慎用存储过程
- 由于应用系统使用存储过程存在调试排错困难的问题，业务逻辑不建议使用存储过程实现，应通过应用程序逻辑实现。

## 5.13 频繁更新表
- 对于频繁更新的表，建议建表时指定表的 fillfactor=85,每页预留 15%的空间给 HOT 更新使用。

## 5.14 宽表查询
- 对于宽表，宜将前台列表查询所涉及字段外其它字段分开设计到另一张表。注意，另一张表只有在前台列表中选择单个记录时，再关联。
