表设计规范
1、表名不使用复数名词。
说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯。
2、表名使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只出现数字。
说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、表名、都不允许出现任何大写字母,避免节外生枝。
正例:aliyun_admin,rdc_config,level3_name
反例:AliyunAdmin,rdcConfig,level_3_name
3、表的命名最好是遵循“业务名称_表的作用”。
正例:sys_user / force_project / trade_config
4、表和列的名称必须控制在32个字符以内,表名只能使用字母、数字和下划线,一律小写。如表名过长可以采用缩写等方式。【特例:oracle要求是一律用大写】
5、创建表时必须显式指定字符集为utf8或utf8mb4。
6、创建表时必须显式指定表存储引擎类型,如无特殊需求,一律为InnoDB。当需要使用除InnoDB/MyISAM/Memory以外的存储引擎时,必须通过DBA审核才能在生产环境中使用。因为Innodb表支持事务、行锁、宕机恢复、MVCC等关系型数据库重要特性,为业界使用最多的MySQL存储引擎。而这是其他大多数存储引擎不具备的,因此首推InnoDB。
7、建表必须有comment,表级别和字段级别都要有comment。
8、所有的表中必备id,create_time, update_time, create_user_id, create_user_name, update_user_id, update_user_name七个字段。
说明:用户名等信息可以冗余,提高查询速度。注意的是,只在主表中加入这些字段;由主表产生的副表,关系表中则不用添加这些字段。
9、建议对表里的blob、text等大字段,垂直拆分到其他表里,仅在需要读这些对象的时候才去select
10、中间表用于保留中间结果集,名称必须以tmp_开头。备份表用于备份或抓取源表快照,名称必须以bak_开头。中间表和备份表定期清理。
11、表中的所有字段尽量设置为not null,并采用默认值,字符用EMPTY STRING 数字用默认值0。除非业务上的确需要保存null,可以设置为空。另外表示时间的可以设置为null;但是create_time,update_time表示创建或者更新时间必须设置为not null
说明: https://blog.csdn.net/xiaolyuh123/article/details/105427529/
12、尽量做到冷数据分离,减小表宽度。字段太多的情况,尽量分表,将常用的放在一块,不常用的字段分到其他表中,有效减少磁盘的IO,保证热数据的缓存命中率
13、禁止在表中建立预留字段,以及表中后期废弃的多余字段都需要进行清理。由于无法预知预留字段的类型,后期对改字段进行修改会耗费很多资源,对表进行锁定等问题
表字段设计规范
1.、表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint(1 表示是,0 表示否)。
说明:任何字段如果为非负数,必须是 unsigned。
注意:POJO 类中的任何布尔类型的变量,都不要加 is 前缀,所以,需要在
正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除;is不可用,建议用has_XXX替代
表达状态时,最好从1开始递增。如:性别非必填,但是数据库中设计的时候,要求为NOT NULL,并且默认值为0;那么某个用户,性别没有填,保存到数据库,性别会默认填充0,如果用(0表示男,1表示女)会出现问题,页面上用户上没选择性别,这时数据回显,会默认性别为男了。
2、字段名必须使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只出现数字。
说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。
正例:aliyun_admin,rdc_config,level3_name
反例:AliyunAdmin,rdcConfig,level_3_name
3、禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。
4、小数类型为 decimal,禁止使用 float 和 double。
说明:在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。
5、如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
6、varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text ,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
说明:varchar(255) 和 varchar(256)区别
https://www.jianshu.com/p/83bdcf9bd5a8
7、如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。
8、字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
1) 不是频繁修改的字段。
2) 不是唯一索引的字段。
3) 不是 varchar 超长字段,更不能是 text 字段。
正例:各业务线经常冗余存储商品名称,避免查询时需要调用 IC 服务获取。
9、单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。
10、合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
正例:无符号值可以避免误存负数,且扩大了表示范围。表示状态或者类别建议使用tinyint或samllint存储
11、主键用id表示,设置为int ,自增,无符号。
说明:500W以上规模数据,存储空间能节约一半;效率高,比较数字比比较字符串效率高;方便sql性能优化(可以替代大部分场景进行排序操作)
例如sql语句优化处理,分页查找
select * from table limit 5000000,10这么查询效率比较低
可以改为 select * from table where id>5000000 limit 10;
12、日期类型建议使用时间戳bigint
说明:比较数字永远比字符串快
https://www.jianshu.com/p/b22ac1754372
13、无需建立表与表之间的外键约束,但是得有表达外键关系的字段。命名规则为 表名_id
说明:sys_user表 外键则为user_id
14、业务中IP地址字段推荐使用int类型,不推荐用char(15)。因为int只占4字节,可以用如下函数相互转换,而char(15)占用至少15字节。一旦表数据行数到了1亿,那么要多用1.1G存储空间。 SQL:select inet_aton('192.168.2.12'); select inet_ntoa(3232236044);
索引设计
1、InnoDB表必须主键为id int/bigint auto_increment,且主键值禁止被更新。
2、唯一键以“uk_”或“uq_”开头,普通索引以“idx_”开头,一律使用小写格式,以字段的名称或缩写作为后缀。
3、InnoDB和MyISAM存储引擎表,索引类型必须为BTREE;MEMORY表可以根据需要选择HASH或者BTREE类型索引。
4、单个表上的索引个数不能超过5个。
5、建表或加索引时,保证表里互相不存在冗余索引。对于MySQL来说,如果表里已经存在key(a,b),则key(a)为冗余索引,需要删除。
6、业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。
说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
例如: 用户角色,可以将用户和角色组合成唯一索引
7、超过三个表禁止 join 。需要 join 的字段,数据类型保持绝对一致 ; 多表关联查询时,保证被关联的字段需要有索引。
说明:即使双表 join 也要注意表索引、SQL 性能。
8、在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。
说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度来确定。
9、页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
10、如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
正例:where a=? and b=? order by c; 索引:a_b_c
反例:索引如果存在范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。
11、建组合索引的时候,区分度最高的在最左边。
正例:如果 where a=? and b=?,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。
说明:存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如:where c>? and d=? 那么即使 c 的区分度更高,也必须把 d 放在索引的最前列,即建立组合索引 idx_d_c。
12、防止因字段类型不同造成的隐式转换,导致索引失效。
13、创建索引时避免有如下极端误解:
1) 索引宁滥勿缺。认为一个查询就需要建一个索引。
2) 吝啬索引的创建。认为索引会消耗空间、严重拖慢记录的更新以及行的新增速度。
3) 抵制惟一索引。认为惟一索引一律需要在应用层通过“先查后插”方式解决。
14、常见索引列建议:where从句中的列 order by、group by、distinct 中的字段,多表join的关联列,如果在字句中是单个列,那就单独索引,有多个列,那可以建立联合索引