<div align=center><font size=5>众望通科技 研发中心</font></div>
<div align=center><font size=6>数据库设计规范</font></div>

> 拟稿：周志尧
>
> <div><font>版本号 1.0.4 </font></div>
>
> 1. 修改：修改数据库设计概述、行业规范、数据库命名字母大小写规范的内容描述
> 2. 新增：新增数据库命名分段命名原则的示例表
> 3. 去除：去除数据库命名长度受限原则的示例表



[TOC]

# 数据库设计概述

本设计规范只适用于关系型数据库。

## 数据库选型

#### 推荐选型

* 开源数据库

> PostgreSQL、MySQL

* 商业数据库

> Oracle

* 国产数据库 

> 国家信创产品

#### 不推荐选型

> DB2、Sybase

# 命名规范

## 通用命名规范

##### <font  color= #8470FF>Ø规范</font>：遵循行业规范
当有相关国家/行业强制性数据结构标准规范存在时，用于存储业务数据的业务表，在表名命名上原则上应该遵从标准规定，其表中相关字段的中文名称（即数据项名称），若标准规范上有规定的应遵循规定。此外，若标准规范上对数据项的类型、长度有规定的，原则上也应当遵循或保证能直接兼容保存和访问。

##### <font  color= #8470FF>Ø规范</font>：字符编码规范

遵循各种数据库推荐的字符编码

| 数据库类型 | 库编码字符集   | 表编码字符集   |
| ---------- | -------------- | -------------- |
| Oracle     | simple Chinese | simple Chinese |
| MySQL      | utf8mb4        | utf8mb4        |
| PostgreSQL | utf-8          | utf-8          |
| DB2        | gbk            | gbk            |

##### <font  color= #8470FF>Ø规范</font>：字母大小写规范
所有数据库对象命名（库、表、字段、视图、索引）字母，遵循各种数据库推荐的大小写规范：

| 数据库类型 | 表名大小写                                               | 字段名大小写                                             | 库名大小写                                    | 视图名大小写                                  | 索引名命名规范                     |
| ---------- | -------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------- | --------------------------------------------- | ---------------------------------- |
| Oracle     | 统一使用大写 | 统一使用大写                  | 统一使用大写 | 统一使用大写 | 统一使用大写 |
| MySQL      | 统一使用小写 | 统一使用小写 | 统一使用小写 | 统一使用小写 |统一使用小写|
| PostgreSQL | 统一使用小写           | 统一使用小写                         | 统一使用小写 | 统一使用小写 | 统一使用小写 |
| DB2        | 统一使用大写 | 统一使用大写 | 统一使用大写 | 统一使用大写 | 统一使用大写 |

##### <font  color= #8470FF>Ø规范</font>：长度受限原则

为保证将来系统跨平台的可移植性，表、视图命名长度不超过30个字符

##### <font  color= #8470FF>Ø规范</font>：字符范围原则

只能使用英文字母、下划线、数字进行命名，首位字符必须是英文字母。
##### <font  color= #8470FF>Ø规范</font>：分段命名原则
命名中多个单词间采用下划线分隔，以便阅读同时方便某些工具对数据库对象的映射。如XXX_XXX_XXX，但不限于三段式。

| 数据库类型 | 分段命名原则 | 分段命名示例      |
| ---------- | ------------ | ----------------- |
| Oracle     | XXX_XXX_XXX  | FOOD_BR_TASK_LIST |
| MySQL      | xxx_xxx_xxx  | food_br_task_list |
| PostgreSQL | xxx_xxx_xxx  | food_br_task_list |
| DB2        | XXX_XXX_XXX  | FOOD_BR_TASK_LIST |

##### <font  color= #8470FF>Ø规范</font>：勿用保留词
数据库对象命名，不能直接使用数据库保留关键字，以及Java、JavaScript等常用语言的保留关键字

##### <font  color= #3CB371>Ø建议</font>：同义性原则
对于同一含义尽量使用相同的单词命名，避免同一单词表示多种含义的情况，以免引起误解
##### <font  color= #3CB371>Ø建议</font>：命名方式一致原则
在一个系统、一个项目中尽量采用一致的命名方式，各表之间相同含义的字段，类型定义要完全相同（包括精度、默认值等）；
##### <font  color= #3CB371>Ø建议</font>：扩展性原则
各系统或者项目在遵循本规范的基础上，可以根据需要制定更明确的规范细则，以满足项目管理需要。如对模块进行统一命名，然后用于表名的前缀

## 库命名规范

##### <font  color= #8470FF>Ø规范</font>：数据库名称长度
不超过8个字符

##### <font  color= #3CB371>Ø建议</font>： 库命名
尽量与项目名称一致

## 表命名规范

##### <font  color= #8470FF>Ø规范</font>: 长度规约

表名长度不能超过30，一般不超过五个英文单词，不推荐中文拼音（特定行业规范与约定表述除外）

##### <font  color= #8470FF>Ø规范</font>: 分段命名规约（待进一步商议）

例如：SYS_MOUDLE_ENTITY

SYS 表示所属的系统，一个简写单词（2-5个字符）

MOUDLE 表示数据库对象模块名或者主题分类，一个简写单词（2-5个字符）

ENTITY 表示业务实体名称，可以根据需要有多个单词组成（1-3个单词，用下划线连接）

##### <font  color= #8470FF>Ø规范</font>: 命名前缀规范（待进一步商议）

> 系统参数表	SYS_

> 用户、权限表	U_

> 系统日志表  LOG_

> 代码表

> 字典表	DT_

> 临时表   TMP_



## 字段命名规范

##### <font  color= #8470FF>Ø规范</font>：长度规范

字段长度不能超过20

##### <font  color= #8470FF>Ø规范</font>：前缀规范

列名无需使用前缀

##### <font  color= #8470FF>Ø规范</font>：多段式命名（待议）

列名采用多段式命名时，各单词间用下划线分隔

##### <font  color= #3CB371>Ø建议</font>：特定类型字段命名

日期类型字段：推荐以 DATE 结尾的名字命名

时间类型字段：推荐以 TIME 结尾的名字命名

##### <font  color= #3CB371>Ø建议</font>：主键列命名

为 ID 或者以  ID 为后缀进行命名，对于需要在其它表中引用的主键字段以“_ID”后缀方式命名

## 视图命名规范

##### <font  color= #8470FF>Ø规范</font>：前缀规范

视图的命名以V_开头
##### <font  color= #8470FF>Ø规范</font>：视图其它命名规范


参考表的命名规范

##### <font  color= #3CB371>Ø建议</font>：视图的列名

一般与基表一致，但是根据需要可以与基表的列名不同。


## 索引命名规范
##### <font  color= #8470FF>Ø规范</font>：前缀规范
索引的命名以IDX_开头,中间接表名，后面接字段名，如:IDX_TRENTBASE_PRIPID

# 基本设计规范

## 字段设计规范

##### <font  color= #8470FF>Ø规范</font>：主键

主键为带横杆的UUID，主键不表示任何业务含义

##### <font  color= #8470FF>Ø规范</font>：公共字段

ID 编号 VARCHAT(36)

Create_Time 创建时间 TIMESTAMP --默认为系统当前时间

Update_Time 修改时间 TIMESTAMP --默认为系统当前时间

交给持久化框架完成更新，SQL不需要特别编写

##### <font  color= #8470FF>Ø规范</font>：时间类型

一般时间精度使用DATE，保存到秒，例如“2010-11-22 11:22:36”

高精度使用TIMESTAMP，保存小数秒，例如“2010-11-22 11:22:36.000000”

特别说明：PostgreSQL数据库的DATE类型只精确到日期，无法保存时分秒，建议使用TIMESTAMP

##### <font  color= #8470FF>Ø规范</font>：数字、小数类型

不得使用VACHAR等字符串类型来保存，应该使用相应精度的数字、小数类型，确保定义时有默认值

##### <font  color= #8470FF>Ø规范</font>：财务金额类型

财务相关的金额类，必须使用decimal类型，确保定义时有默认值

##### <font  color= #8470FF>Ø规范</font>：大对象字段

ORACLE: 禁止使用CLOB类型保存大文本、图片和文件

MySQL：尽量不要使用TEXT数据类型，varchar类型支持65535字节，满足大多数场景

禁止数据库中存储图片、二进制数据，使用其他方式存储（例如文件系统，数据库只保存其地址信息）

##### <font  color= #8470FF>Ø规范</font>：表示状态的字段（码值）

表示简单状态的字段，字段not null，根据业务要求来设置默认值（例如默认为0）

对于Boolean类型，以1代表是（true）， 0 代表否（false）


## 公共规范
##### <font  color= #8470FF>Ø规范</font>：冗余字段

 反范式化冗余字段使用规范，考虑具体使用场景，当SQL关连查询比较频繁，或涉及到4张以上表时可考虑采用冗余字段

##### <font  color= #8470FF>Ø规范</font>：注释

所有表和字段都需要添加注释

表示状态的字段，注释中应该注明每一种状态的含义，例如“0：编辑中，1：审核中，2：已完成”

##### <font  color= #8470FF>Ø规范</font>：默认值设置

冗余字段尽可能把所有列定义为NOT NULL，定义时设置默认值

##### <font  color= #8470FF>Ø规范</font>：字段数限制

表的字段数不超过50个

##### <font  color= #3CB371>Ø建议</font>：逻辑删除标识设计

表中应有数据对应逻辑删除标识，用逻辑删除代替物理删除，标识数据是否已删除

##### <font  color= #3CB371>Ø建议</font>：关联字段索引设计原则

对于数据量大的情况下，建议将数据库字段中相关联字段进行索引添加，以提高相关关联查询效率

##### <font  color= #3CB371>Ø建议</font>：复合主键设计原则

对于部分简单的中间关联表，可设置表关联的复合主键，提高储存和索引效率，不建议使用业务相关字段作为复合主键

##### <font  color= #3CB371>Ø建议</font>：分区或分表设计原则

当数据量太大导致影响到查询速度或操作速度的时候，可根据实际情况进行分区或分表进行数据储存

##### <font  color= #3CB371>Ø建议</font>：冷热数据分离

尽量做到冷热数据分离，减小表的宽度



# 管理规范

##### DDL管理

代码表的方式，PDM的方式

##### 权限管理

分离运维账号、开发账号、系统运行账号

##### 数据字典管理

启动开发时建立数据字典，管理命名中使用的英文单词、英文单词缩写、拼音首字母缩写等，对用于命名的单词进行统一管理

##### 规范管理

DDL定义必须符合本设计规范，通过脚本校验工具（规避关键字、强制规范的校验）

# 基本理论基础

> 数据设计的三个范式 3NF 
>
> 1. 表内的每一个记录都只能被表达一次；
> 2. 表内的每一个记录都应该被唯一的标识（有唯一键）；
> 3. 表内不应该存储依赖于其他键的非键信息。


# 表的优化与列类的选择
总结：数据库优化无非就两个方面：“空间换时间，时间换空间”。几十年前内存比较小，那个时候写程序就是一个字节一个字节的扣，看谁用的内存少， 现在硬件都是廉价的，1T的固态加上上百G的内存都不算什么，所以现在都是什么东西都是往内存一扔，如，以前有1G的文本，要统计数量，这个在现在就比较落伍了，直接往内存一扔，暴力统计下就可以了。第三点就是磁盘上多费点，换取时间的取胜。

1、定长与变长分离
如：id int，占4个字节，char(4)占4和字符长度，也是定长。

即每一单元的值的字节是固定的
核心且常用字段，宜建成定长，放在一张表
如：用户姓名，等级是常用的，放在一张表里面，而E-mail,电话这些信息要点进去才能看，可以放在另外一张表


而varchar,text,blob这种变长字段，合适存放一张表，并用主键和核心表关联起来

2、常用字段和不常用字段要分离
需要结合网站具体的业务来分析，分析字段的查询场景，查询频率低的字段，拆分出来。

3、在一对多需要关联统计的字段上，添加冗余字段，用于统计分析
数据库设计一般有范式，范式越高，表就拆分的越细，但是这样设计不好，我们在设计中一般是反范式。
比如论坛，栏目，下面有个统计今日发文的数量，一般是 两表联合查询，这样比较消耗资源，我们可以添加一个【数量】的字段，每次发文就加1，每天清零，这样增加速度

列类型的选择
1、字段类型的优先级：
整型>date,time>char>varchar>text
列的特点分析：
1>整型：定长，没有国家、地区之分，没有字符集的差异
比如：tinyint 1,2,3,4,5 <----> char(1) a,b,c,d,e
从空间上，都是占用1个字节，但是 order by 排序，前者快
原因：后者需要考虑字符集与校对集（排序规则、大小写）
比如【 a B c D】 我们正常来说排序就是【 a B c D】 ，但是计算机是【  B  D a c】 

2>time定长，运算快，节省空间，考虑失去，写sql时不方便 where>'2005-10-12'
3>enum 能起约束表值的目的，内部用整数型来存储，单与char联查时，内部要经历串与值的转化
4>char 定长， 考虑字符集和排序，校对集
5>varchar,不定长，要考虑字符集的转换与排序时的校对集，速度慢
6>text 等大字段 无法使用内存临时表（排序操作只能在磁盘上进行）

以性别为例:
char(1),3个字长字节
enum('男','女') //内部转成数字来存，多了一个转换过程
tingint ,//0 1 2//定长字节

2、够就行，不要慷慨
原因：大的字段浪费内存，影响速度
以年龄为例tinyint unsigned not null，可以存储255岁，足够，用int浪费了3个字节
以varchar(100)，varchar(300)存储相同的内容，单在表联查时，varchar(300)要花更多内存


3、尽量避免使用NULL()--mysql数据库的
原因:NULL，不利于索引，要用特殊的字节来标注；
在磁盘上占据的空间其实更大（mysql5.7已对null做了改进，但查询还是不便）

# 索引
数据库查询只会用到一个索引

1、在where 条件常用的列上，都加上索引
例：where id=3 and price>100 //查询栏目3，价格为100元以上的商品
误：id上和price上都加上索引
答：只能用上id或price索引，因为是独立的索引，同时只能用上1个

2、在多列上建立索引后，查询哪个列，索引都将发生作用
误：多列索引上，索引发挥作用，需要满足左前提要求

# 表更新
1、所有的执行语句必须加上事务，确定没有问题才能提交，更新数据范围不能超过100列，如果超过这个数，就必须DBA联系处理