数据库开发规范参考

最近做一个小项目时要自行设计数据库,因此对数据库的相关设计规范进行了回顾,整理起来作为总结备忘,也为以后的数据库设计提供参考。


一. 命名规范
  • 数据库 对象名称必须使用小写字母并用下划线规范
  • 数据库对象名称禁止使用 MySQL 保留关键字
  • 数据库对象命名要做到见名识义,并且最好不要超过 32 个字符
  • 对于临时表,最好以 tmp 为前缀,以日期为后缀进行特别标识
  • 对于备份表必须以 bak 为前缀并以日期为后缀
  • 所有存储相同数据的列名和列类型必须一致。这种列通常作为关联列,保证类型和命名一致会提高查询速度,否则关联时数据库会进行隐式转换,不一致的话会降低性能

二. 基础设计规范

1. 使用 Innodb 存储引擎
  • 5.5 之前默认使用 Myisam 存储引擎,现在默认使用的是 Innodb。正常情况下都应该使用 Innodb 存储引擎
  • Innodb 存储引擎支持事务,行级锁,更好的恢复性和高并发下的更好性能
2. 使据库和表的字符集统一使用 UTF8 字符集
  • 可以避免由于字符集转换产生的乱码
  • 重点在于数据库和表字符集的统一
  • UTF8 字符集汉字占3个字节,ASCII 码占用 1 个字节
3. 所有的表和字段都要添加注释
  • 使用 comment 语句添加条和列的备注
  • 从一开始就方便维护
4.尽量控制单表数据量控制在 500 万行以内
  • 注意这是一条规范,取决于存储设备和文件系统,MySQL 没有限制
  • 可以使用历史数据归档和分库分表的方式来维持表的数量在一个合理范围内
5.谨慎使用 MySQL 分区表
  • 虽然理论 MySQL 分区表查询性能有所提高,但还是要谨慎选择分区键,在跨分区查询效率可能更低,对于大表使用分库分表更加靠谱
6. 做到冷热数据分离,减少表的宽度
  • MySQL 限制每行最多 4096 列,且每一行数据大小不能超过 65535 字节
  • 限制数据可以减少磁盘 IO, 保证热数据的内存缓存命中率
  • 可以更有效的利用缓存,避免读入无用的冷数据
  • 把经常使用的数据存储到同一个表中
7. 禁止在表中建立预留字段
  • 预留字段很难见名识义
  • 预留字段无法选择合适的类型
  • 对预留字段类型进行修改会对表进行锁定
  • 修改表中列的操作所耗费的资源远远大于添加一个字段
8. 禁止在数据库中存储图片,文件等二进制操作
  • 数据过大会对降低性能
  • 正确的做法是存储到专门的文件服务器中,数据库只需要记录其存储位置即可
9.禁止在线上做数据库压力测试
  • 会对正常业务造成影响
  • 会产生大量垃圾数据,影响正常业务
  • 要使用测试环境,然后评估正式环境的性能,不能使用正式环境
10.不同的数据库环境要进行隔离
  • 便于开发和测试

三. 索引设计规范

1. 不要滥用索引
  • 限制表中索引列的数量,建议每张表不超过 5 个索引
  • 索引会提高查询效率,但会降低插入和更新效率,有时候也会降低查询序列
  • 禁止给每一个列建立单独的索引
2. 每个 Innodb 必须有一个主键
  • Innodb 是按照主键的顺序来组织表的,因此每个 Innodb 表必须有一个主键
  • 不能使用频繁更新的和多列作为主键,那样会降低性能
  • 不要使用 UUID, MD5, HASH, 字符串列作为主键,无法保证自增
  • 选择可以保证不重复以及可以自增的列作为主键
3. 常见索引列建议
  • 对出现在 SELECT, UPDATE, DELETE 语句的 WHERE 从句中的列建立索引
  • 对包含在 ORDER BY, GROUP BY, DISTINCT 中的字段建立索引
  • 必须对每个列添加索引,可以使用联合索引
  • 多表 JOIN 的关联列
4. 联合索引中索引列的顺序
  • 区分度最高的列放在联合索引的最左侧
  • 尽量把字段长度小的列放在左侧
  • 把最频繁的列放到联合索引的左侧
5. 避免建立冗余和重复索引
  • 会降低性能
6. 尽量避免使用外键
  • 不建议使用外键约束,但是要在关联列建立索引
  • 外键会影响父表与子表的写操作从而降低性能
  • 外键约束要在业务端实现

四. 数据库字段设计规范

1. 优先选择符合需要的最小的数据类型

用 《高性能 MySQL》中的说法就是“越小越好”

  • 尽量将字符串转为数字类型的存储,使用INET_ATON()和 INET_NTOA() 对字符串与数字类型进行转换转换
  • 对于非负数据采用无符号整型进行存储
  • VARCHAR 中的 N 代表的是字符串而不是字节数,255 代表可以保存255个字符,也就是说可以保存 255 个中文,会占用 765 字节
  • 过大长度会消耗更多内存
2. 避免使用 TEXT和 BLOB
  • 一般使用 varchar 数据类型就足够了
  • 对这种数据会进行二次查询,效率较低
  • 一定要使用的话建议将 BLOB 和 TEXT 分离到单独的表中且不要使用 SELECT * 进行检索
  • TEXT 和 BLOB 只能使用前缀索引且不能有默认值
3. 避免使用 ENUM 枚举数据类型
  • 修改 ENUM 值需要使用 ALTER 语句, 频繁的修改会造成失误,有一定风险
  • 其 ORDER BY 时要先进行转换在排序,效率较低
  • 禁止使用数值作为 ENUM 的枚举值
4. 尽可能的将所有列定义为 NOT NULL
  • 索引 NULL 列 需要额外的空间来保存,会占用更多的空间
  • 进行比较和计算时要对 NULL 做额外处理
5. 使用 TIMESTAMP 或者 DATETIME 来存储时间
  • 不要使用字符串来存储日期和时间类型
  • TIMESTAMP 占用空间小但是取值范围小,为 1970-01-01 00:00:01 ~ 2038-01-19 03:14:09
6. 同财务相关的金融类数据使用精确浮点数
  • 同财务有关的金额类数据必须使用 decimal 类型,不会在计算的时候丢失精度
  • decimal 可以存储比 bigint 更大的整数数据
  • 占用的空间由定义的宽度决定,每四个字节存储 9 位数字,小数点占用一个字节

五. SQL 开发规范

1. 使用预编译语句进行数据库操作
  • 只传参数,比传递 SQL 语句高效, 一次解析,多次使用
  • 可以避免 SQL 注入攻击
2. 尽量避免数据类型的隐式转换
  • 会导致索引失效
3. 充分利用表上已经存在索引
  • 避免使用双 % 查询条件
  • 一个 SQL 只能利用复合索引中的一列进行范围查询
  • 使用 left join 或者 not exists 优化 not in,后者会使索引失效
4.禁止跨库查询
  • 程序连接不同的数据库要使用不同的账号
  • 为数据库迁移和分库分表留出余地
  • 降低业务耦合度
  • 避免权限过大产生的安全风险
5. 禁止 select * 查询。使用字段名指明
  • 返回结果包含许多不必要的字段,会消耗更多的资源,包括带宽、IO资源、CPU 资源
  • 无法使用覆盖索引
  • 减少表结构变更带来的影响
6.禁止使用不含字段列表的 insert 语句
  • 要明确指定插入的列名和对应的值
  • 可以减少表结构变更带来的影响
7. 禁止子查询,可以优化为 join 操作
  • 子查询结果集无法使用索引,查询性能很低
  • 会产生临时表,消耗 CPU 和 IO 资源,数据量大会降低性能
8. 避免使用 JOIN 关联太多表
  • MySQL 会有关联缓存,关联表过多的话会占用大量内存
  • 会产生临时表操作影响查询效率
  • MySQL 最多可以关联 61 个表,实际建议不超过 5 个表
9. 减少与数据库的交互次数
  • 数据库更适合批量操作
  • 合并多个操作一次执行,可以提高处理效率
10. 使用 in 代替 or
  • in 中的值不要超过 500 个
  • in 可以更有效利用索引
11. 禁止使用 order by rand() 进行随机排序
  • 对性能有很大的影响
  • 该语句会把表中所有符合条件的数据加载到内存中并进行排序,会消耗大量的资源
  • 推荐首先在程序中获取一个随机值,然后从数据库中获取数据
12. 禁止在 where 从句中对列进行函数转换和计算
  • 会导致列无法使用索引
  • 将转换操作进行优化或者放到代码中转换
13. 明显不会有数据重复值时使用 union all 而不是 union
  • 后者会把数据放到临时表中再进行去重操作,结果很大时会消耗大量的资源
  • union all 不会进行去重操作
14. 合理拆分一个大 SQL 为 多个小 SQL
  • MySQL 一个 SQL 只能使用一个 CPU 进行计算
  • 拆分后可以利用多个 CPU 进行并行操作

你可能感兴趣的:(数据库,数据库,mysql,开发规范)