MySQL 数据库设计规范 详解

1> 数据库涉及字符规范
采用 26 个英文字母(区分大小写) 和 0-9 这十个自然数,加上下划线'_'组成, 共 63 个字符,不能出现其他字符(注释除外)
注 :  1> 以上命名都不得超过 30 个字符的系统限制,变量名的长度限制为 29(不 包括标识字符@)
       2> 数据对象、变量的命名都采用英文字符,禁止使用中文命名。绝对不要在对 象名的字符之间留空格
       3> 小心保留词,要保证字段名没有和保留词、数据库系统或者常用访问 方法冲突
       4> 保持字段名和类型的一致性,在命名字段并为其指定数据类型的 时候一 定要保证一致性。假如数据类型在一个表里是整数,那在另一个表里可就别变成字 符型

2> 数据库命名规范
数据库名使用小写英文以及下划线组成,比如 :  my_db snepr
备份数据库名使用正式库名加上备份时间组成,如 :  dbname_20070403

3> 数据库表命名规范
数据表名使用小写英文以及下划线组成, 比如 :
    info_user
    system_destination
信息类采用 : info_xxx
文件类采用 : file_xxx
关联类采用 : inter_xxx
备份数据表名使用正式表名加上备份时间组成,如 :
    info_user_20070403
    system_destination_20070403

4> 字段命名规范
字段名称使用单词组合完成,首字母小写,后面单词的首字母大写,最好是带 表名前缀, 如 web_user 表的字段 :
    userId
    userName
如果表名过长,可以取表名的前5个字母。如果表名为多个单词组合,可以 取前一个单词,外加后续其它单词的首字母作为字段名
表与表之间的相关联字段要用统一名称, 如 info_user 表里面的 userId 和 group 表里面的 userId 相对应
业务流水号统一采用 : 表名_seq
注 : 字段名前面增加表名,就不用担心在多表查询时对同名字段的冲突

表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑
正例 : getter_admin, task_config, level3_name
反例 : GetterAdmin, taskConfig, level_3_name

表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint(1 表示是, 0 表示否)  ,此规则同样适用于 odps 建表
说明 : 任何字段如果为非负数,必须是 unsigned

表名不使用复数名词
说明 : 表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数 形式,符合表达习惯

唯一索引名为 uk_字段名;普通索引名则为 idx_字段名
说明 : uk_ 即 unique key;idx_ 即 index 的简称

小数类型为 decimal,禁止使用 float 和 double
说明 :  float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储

如果存储的字符串长度几乎相等,使用 char 定长字符串类型

varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率

表必备三字段 : id, gmt_create, gmt_modified
说明 : 其中 id 必为主键,类型为 unsigned bigint、单表时自增、步长为 1。 gmt_create,  gmt_modified 的类型均为 date_time 类型

表的命名最好是加上“业务名称_表的作用”
正例: tiger_task / tiger_reader / mpp_config

库名与应用名称尽量一致

单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表
说明 : 如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表

5> 外键命名规范
外键名称为 FK_表名_A_表名_B_关联字段名
其中表名和关联字段名如果过长,可以取表名、关联字段名的前5个字母
如果表名、关联字段为多个单词组合,可以取前一个单词,外加后续其它单词的
首字母作为字段名
如 : FK_user_token_user_phnum;

6> 字段类型规范
规则 : 用尽量少的存储空间来存数一个字段的数据
    <1> 能用 int 的就不用 char 或者 varchar
    <2> 能用 varchar(20) 的就不用 varchar(255)
    <3> 时间戳字段尽量用 int 型,如 created:表示从'1970-01-01 08:00:00'开始 的 int 秒数,采用英文单词的过去式;gmtCreated:表示 datetime 类型的时间, 即形如'1980-01-01 00:00:00'的时间串,Java 中对应的类型为 Timestamp

7> 索引使用原则
     < 1> 逻辑主键使用唯一的成组索引,对系统键 (作为存储过程) 采用唯一的非成 组索引,对任何外键列采用非成组索引。考虑数据库的空间有多大,表如何进行访 问,还有这些访问是否主要用作读写
    <2> 大多数数据库都索引自动创建的主键字段,但是可别忘了索引外键,它们 也是经常使用的键,比如运行查询显示主表和所有关联表的某条记录就用得上
    <3> 不要索引 blob/text 等字段,不要索引大型字段(有很多字符),这样作会让 索引占用太多的存储空间
    <4> 不要索引常用的小型表
    <5> 不要为小型数据表设置任何键,假如它们经常有插入和删除操作就更别这样做 ,对这些插入和删除操作的索引维护可能比扫描表空间消耗更多的时间

业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引
说明 : 不要以为唯一索引影响 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做非常完善的校验和控制,只要没有唯一索引,根据墨菲定律, 必然有脏数据产生

超过三个表禁止 join。需要 join 的字段,数据类型保持绝对一致; 多表关联查询 时,保证被关联的字段需要有索引
说明 : 即使双表 join 也要注意表索引、SQL 性能

在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度
说明 : 索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分 度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*) 的区分度 来确定

页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决
说明 : 索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索

如果有 order by 的场景,请注意利用索引的有序性。 order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能
正例 : where a=? and b=? order by c; 索引 : a_b_c
反例 : 索引中有范围查找,那么索引有序性无法利用,如 : WHERE a>10 ORDER BY b; 索引 a_b 无法排序

先快速定位需要获取的 id 段,然后再关联 :  SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

建组合索引的时候,区分度最高的在最左边

创建索引时避免有如下极端误解 :
1> 误认为一个查询就需要建一个索引
2> 误认为索引会消耗空间、严重拖慢更新和新增速度
3> 误认为唯一索引一律需要在应用层通过 "先查后插" 方式解决

不要使用 count(列名)或 count(常量)来替代 count(*),count(*)就是 SQL92 定义 的标准统计行数的语法,跟数据库无关,跟 NULL 和 非NULL 无关
说明 : count(*) 会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行

count(distinct col) 计算该列除 NULL 之外的不重复数量
注 : count(distinct  col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0

当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为 NULL,因此使用 sum()时需注意 NPE 问题
正例 : 可以使用如下方式来避免 sum 的 NPE
问题 : SELECT IF(ISNULL(SUM(g)),0,SUM(g))  FROM table;

使用 ISNULL()来判断是否为 NULL 值,说明 :
1> NULL<>NULL 的返回结果是 NULL, 而不是 false
2> NULL=NULL 的返回结果是 NULL, 而不是 true
3> NULL<>1 的返回结果是 NULL,而不是 true
注 : NULL 与任何值的直接比较都为 NULL

在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句

不得使用外键与级联,一切外键概念必须在应用层解决
说明 : 学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,则为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度

禁止使用存储过程,存储过程难以调试和扩展,更没有移植性

数据订正时,删除和修改记录时,要先 select,避免出现误删除,确认无误才能执 行更新语句

in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内

如果有全球化需要,所有的字符存储与表示,均以 utf-8 编码,那么字符计数方法
说明 :
SELECT LENGTH("轻松工作"); 返回为 12
SELECT CHARACTER_LENGTH("轻松工作"); 返回为 4
如果要使用表情,那么使用 utfmb4 来进行存储,注意它与 utf-8 编码的区别

TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE  无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句
说明 : TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同

POJO 类的 boolean 属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中 进行字段与属性之间的映射
说明 : 参见定义 POJO 类以及数据库字段定义规定,在 sql.xml 增加映射,是必须的

不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需 要定义; 反过来,每一个表也必然有一个与之对应
说明 : 配置映射关系,使字段与 DO 类解耦,方便维护

8> SQL语句规范
所有SQL关键词全部大写,比如 SELECT,UPDATE,FROM,ORDER,BY 等,表名 与字段名不需要大写, 如 :
SELECT COUNT(*) FROM cdb_members WHERE userName='aeolus';

在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明
说明 : 1> 增加查询分析器解析成本  2> 增减字段容易与 resultMap 配置不一致

不要写一个大而全的数据更新接口,传入为 POJO 类,不管是不是自己的目标更新字 段,都进行 update table set c1=value1,c2=value2,c3=value3; 这是不对的。执行 SQL 时,尽量不要更新无改动的字段,一是易出错; 二是效率低; 三是 binlog 增加存储

9>  内容注释
存储过程 , 触发器 , 函数 , 视图等都应该加上内容注释,注释格式如下:
-- =============================================
-- Author:  Tiger
-- Create date: 2009-4-15
-- Description:  根据信息完整度生成客户统计数据
-- Update: 2009-4-30 By  Tiger
-- =============================================
表的陌生字段应当加上简要的字段说明和内容说明

10> 其他设计技巧
     < 1> 避免使用触发器 :  触发器的功能通常可以用其他方式实现,在调试程序时触发器可能成为干扰, 假如确实需要采用触发器,最好集中对它文档化
     < 2> 避免使用存储过程
     < 3> 使用常用英语 (或者其他任何语言) 而不要使用拼音首字母缩写
    <4>  更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值