首页

数据库对象设计规范二(数据库、表、字段、索引、约束设计及存储引擎的选择)

标签:数据库设计,约束设计,索引设计规范,字段设计规范,表设计规范,存储引擎选择     发布时间:2018-02-06   

1. 存储引擎的选择

MySQL支持数个存储引擎作为对不同表的类型的处理器,MySQL中的插件式存储引擎架构是非常有特色的亮点。如无特殊要求,默认使用innodb存储引擎,该引擎为5.6版本中的默认存储引擎。

MySQL引擎

说明

InnoDB

索引和数据都可以缓存到内存中;

支持事务;

支持行级锁,可实现更高的并发度;

支持故障恢复;

支持外键约束;

支持4种不同的事务隔离级别;

2. 字符集的选择

  • Utf8MB4作为字符集的惟一选择。

  • 如使用导出工具,须显式选择utf8mb4作为导出格式。

  • 在开发环境中编写的建库建表脚本及使用工具导出的数据脚本文件,如在进库前需要编辑,必须使用纯文本方式打开,编辑和保存,防止隐含控制字符(如^M)添加进脚本。在Linux环境,可以通过 “cat -A脚本文件名”方式确认和检查是否携带了隐含控制字符。

3. 数据库设计规范

  • 控制单库表个数,建议单库不超过4096个表。

  • 创建数据库的语句必须包含字符集子句和校对规则子句。如:

create database [if not exists]

default character set UTF8MB4 default collate utf8mb4_bin;

4. 表设计规范

  • 表必须要有PK。

  • 一个字段只表示一个含义。

  • 总是包含四个字段:created_time(创建日期),updated_time(修改日期),created_by(创建人),updated_by(修改人) 且这四个字段不应该包含有额外的业务逻辑,在创建或修改记录的时候,必须创建这四个字段。

示例:

创建时间  created_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' ;

修改时间  updated_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改日期';

创建人     created_by VARCHAR2(50) COMMENT '创建人';

修改人     updated_by VARCHAR2(50) COMMENT '修改人';

  • 禁止使用复杂数据类型(数组,自定义等)。

  • 需要join的字段(连接键),数据类型必须保持绝对一致,避免隐式转换。

  • 设计应至少满足第三范式,尽量减少数据冗余。一些特殊场景允许反范式化设计,但在项目评审时需要对冗余字段的设计给出解释。

  • 不建议使用TEXT、BLOB字段。如有需求,建议将TEXT字段放在独立的表中,用PK与主表关联。

  • 单表字段数不要太多,建议最多不要大于50个。

  • MySQL在处理大表时,性能就开始明显降低,所以建议单表物理大小限制在10GB。

  • 如果数据量或数据增长在前期规划时就较大,那么在设计评审时就应加入分表策略。

  • 无特殊需求,严禁使用分区表。

5. 字段设计规范

  • INT:如无特殊需要,存放整型数字使用UNSIGNED INT型。整型字段后的数字代表显示长度。整型类型如下表:

数据类型

最大存储长度(有符号)

最大存储长度(无符号)

tinyint(m)

1个字节 范围(-128~127)

1个字节 范围(0~256)

smallint(m)

2个字节 范围(-32768~32767)

2个字节 范围(0~65535)

mediumint(m)

3个字节 范围(-8388608~8388607)

3个字节 范围(0~16777215)

int(m)

4个字节 范围(-2147483648~2147483647)

4个字节 范围(0~4294967294)

bigint(m)

8个字节 范围(+-9.22*10的18次方)

8个字节 范围(0~1.84*10的20次方)

  • DECIMAL(M,D):定点小数使用此DECIMAL类型,且明确标识出为无符号型(UNSIGNED),除非确实会出现负数。

  • DATE:所有只需要精确到天的字段全部使用DATE类型,而不应该使用TIMESTAMP或者DATETIME类型。

  • DATETIME:所有需要精确到时间(时分秒)的字段均使用DATETIME,不要使用TIMESTAMP类型。

  • VARCHAR:所有动态长度字符串 全部使用VARCHAR类型,类似于状态等有限类别的字段,也使用可以比较明显表示出实际意义的字符串,而不应该使用INT之类的数字来代替;VARCHAR(N),N表示的是字符数而不是字节数。比如VARCHAR(255),可以最大可存储255个字符(字符包括英文字母,汉字,特殊字符等)。但N应尽可能小,因为MySQL一个表中所有的VARCHAR字段最大长度是65535个字节,且存储字符个数由所选字符集决定。如UTF8存储一个字符最大要3个字节,那么varchar在存放占用3个字节长度的字符时不应超过21845个字符。同时,在进行排序和创建临时表一类的内存操作时,会使用N的长度申请内存。
    如无特殊需要,原则上单个varchar型字段不允许超过255个字符。

  • CHAR:仅仅只有单个字符的字段使用CHAR(1)类型,例如性别字段。

  • TEXT:仅仅当字符数量可能超过20000个的时候,才可以使用TEXT类型来存放字符类数据,因为所有MySQL数据库都会使用UTF8字符集。所有使用TEXT类型的字段必须和原表进行分拆,与原表主键单独组成另外一个表进行存放。如无特殊需要,严禁开发人员使用MEDIUMTEXT、TEXT、LONGTEXT类型。

  • 使用INT UNSIGNED型存储IPV4。PHP程序推荐使用long型存储IPV4(非强制)。

  • 对于精确浮点型数据存储,需要使用DECIMAL,严禁使用FLOAT和DOUBLE。

  • 如无特殊需要,严禁开发人员使用BLOB类型。

  • 如无特殊需要,字段必须使用NOT NULL属性,可用默认值代替NULL。MySQL NULL类型和Oracle的NULL有差异,会进入索引中。此外,NULL在索引中的处理也是特殊的,也会占用额外的存放空间。

  • 不建议使用ENUM、SET类型,使用TINYINT来代替。

  • 每个列定义的时候必须加上COMMENTS。

  • 自增字段类型必须是整型且必须为UNSIGNED,推荐类型为INT或BIGINT,并且自增字段必须是主键或者主键的一部分。

  • 日期类型的字段不能使用VARCHAR或者CHAR类型,只能使用DATE、DATETIME字段类型存放。

6. 索引设计规范

  • 索引必须创建在索引选择性选择性较高的列上。
    索引选择性:索引列中不同值的数目与表中记录数的比值。如SEX字段共100条记录,只存放男、女两个值,则在SEX列上创建的索引idx_sex的索引选择性为2/100=0.02

组合索引的首字段,必须在where条件中。

  • 对于确定需要组成组合索引的多个字段,建议将选择性高的字段靠前放。

  • 禁止使用外键,容易产生死锁,应由程序保证参照完成性。

  • Text类型字段必须使用前缀索引。

  • 单张表的索引数量理论上应控制在5个以内。经常有大批量插入、更新操作表,应尽量少建索引。

  • 组合索引中的字段数建议不超过5个。

  • 禁止对过长(MySQL的varchar索引只支持不超过768个字节,UTF8是三字节,即:768/3=256,所以字段最长为255)的VARCHAR类型字段建立索引,除前缀索引外超过32字节的varchar列加索引需要DBA评估。如果需要对超过32字节的varchar列整列进行完全匹配,需要新增一个字段,该字段是varchar列的md5值,使用md5来进行完全匹配;这种情况下,就无法进行范围查询。

7. 约束设计规范

  • PK应该是有序并且无意义的,尽量由开发人员自定义,且尽可能短,使用自增序列。建议ID BIGINT

  • 表中除PK以外,还存在唯一性约束的,可以在数据库中创建以“uk_”作为前缀的唯一约束索引。

  • PK字段不允许更新。

  • 禁止创建外键约束,外键约束由应用控制。

  • 如无特殊需要,所有字段必须添加非空约束。

  • 如无特殊需要,所有字段必须有默认值。