数据库设计以及优化

数据库设计规范

1.数据库命名规范

  • 规范:数据库对象名称(数据库名、表名、列名等)必须使用小写字母并用下划线分割
    说明:Linux系统大小写敏感,因此MySQL也是大小写敏感。为了避免混淆,统一使用小写。
  • 规范:所有数据库对象名称禁止使用MySQL保留关键字。
    说明:会产生SQL语法错误,比如select id,from from user;(from为关键字),解决方法是把from字段用反引号(键盘上数字1键的左边那个键`)括起来:
select id,`from` from user;

为了避免不必要的麻烦,请不要使用保留关键字作为数据库对象名称。MySQL关键字可以使用https://dev.mysql.com/doc/refman/5.7/en/keywords.html查询。

  • 规范:数据库对象的命名要做到见名知意,并且最好不要超过32个字符。
    说明:32个字符不是MySQL本身限制的长度,但是命名太长在使用过程中很不方便,也会增加网络传输的开销。
    如:tb_userdb,tb=淘宝,user=用户,db=数据库,表示为淘宝网的用户数据库;user_account,user=用户,account=账号,表示用户数据库下的账号表
  • 规范:临时库表必须以tmp为前缀并以日期为后缀。
    说明:tmp表示临时,日期为后缀是为了方便后续管理,比如根据时间清理临时库表。
  • 规范:备份库、表必须以bak为前缀并以日期为后缀。
    说明:bak表示备份,日期为后缀是为了方便后续管理,比如根据恢复、清理备份库表。
  • 规范:所有存储相同数据的列名和列类型必须一致。
    说明: 如下,user_id存在于2个表中,名称一致,类型一致。
    这种列(存储相同数据的列)一般是关联列,对查询性能有很大影响。如果2个表的关联列数据类型不一致,则在关联时会进行隐式类型转换,会造成列上的索引失效,使得查询效率大幅度变低。
create table user(
user_id unsigned int unsigned auto_increment not null,
……
)
create table order(
order_id int primary key auto_increment,
user_id int unsigned not null,
)

2.数据库基本设计规范

  • 规范:所有表必须使用Innodb存储引擎。
    说明:一般使用Innodb存储引擎,除非它无法满足特殊需求,比如列存储等。
    5.6之后,Innodb为默认存储引擎;
    支持事务,行级锁,更好的恢复性,高并发下性能更好;
    等等。
  • 规范:数据库和表的字符集统一使用UTF8。
    说明:UTF8兼容性好。不是说一定要用UTF8,只是说要“统一”,避免乱码。
    如果编码不统一,在数据库迁移时会造成很多问题,在进行字符比较时会先转码从而使索引失效造成性能下降。
    MySQL中UTF8字符集汉字占3个字节,ASCII码占1个字节。
  • 规范:所有表和字段都需要添加注释。
    说明:使用comment从句添加备注,为了从一开始就进行数据字典的维护。
CREATE TABLE `user` (
	`name` VARCHAR(50) NOT NULL COMMENT '用户姓名',
	……
)
COMMENT='用户表'
ENGINE=InnoDB
;

  • 规范:尽量控制单表数据量的大小,建议控制在500万行以内。
    说明:
    500万行不是MySQL数据库的限制。
    单表数据量过大,对查询性能、修改表结构、备份、恢复都有很大影响。
    MySQL可以存储的数据量限制取决于存储设置和文件系统:32位对单文件大小有限制。
    如何控制单表数据量:历史数据归档(日志数据)、分库分表(业务数据)等手段。
  • 规范:谨慎使用MySQL分区表。
    说明:
    分区表在物理上表现为多个文件,在逻辑上表现为一个表。
    使用分区表能更好的提高性能,是有条件的,最好的情况是:分区表的不同分区文件可以存储在不同的磁盘阵列上。
    谨慎选择分区键。
    避免跨分区查询,因为这样效率可能更低。
    因此建议采用物理分表而不是分区表的方式来管理大数据。
  • 规范:尽量做到冷热数据分离,减少表的宽度。
    说明:
    MySQL对列的宽度限制4096列,每一行数据限制为65535个字节。
    好处: 为了减少磁盘IO,保证热数据的内存缓存命中率; 更有效的利用缓存,避免读入无用的冷数据。
    经常一起使用的列放到一个表中。
  • 规范:禁止在表中建立预留字段。
    说明:
    预留字段的命名很难做到见名知意。
    无法选择合适的存储数据类型给预留字段。因此预留字段大部分使用varchar(几乎能存储任何类型的数据),但是这样的话,会降低数据库性能。
    虽然字段名称容易修改,但是,对预留字段类型的修改,会对表进行锁定,严重影响数据库并发性。
    (修改一个字段类型的成本,远大于新增一个字段)
  • 规范:禁止在数据库中存储图片、文件等二进制数据。
    说明:
    存储二进制数据一般用BLOB等大的类型,会影响性能。
    图片等二进制数据通常很大,会短时间内让数据库文件大小快速增长。
    数据读取时会很耗时。
    因此要把二进制文件存放在文件服务器上,数据库只存储文件路径。
  • 规范:禁止在线上做数据库压力测试。
    说明:影响正常业务访问;产生大量垃圾数据;
  • 规范:禁止从开发环境、测试环境直连生产环境数据库。
    说明:容易误操作破坏生产数据的完整性。

3.数据库索引设计规范

  • 规范:限制每张表上的索引数量,建议单张表的索引不超过5个。
    说明:
    索引不是越多越好。
    索引可以增加查询效率,但是会降低插入和更新的效率,某些情况还会降低查询效率。
  • 规范:每个Innodb表必须有一个主键。
    说明:Innodb是按照主键索引的顺序来组织表的,因此每个Innodb表都必须要有一个主键。
    不使用更新频繁的列作为主键(频繁更新主键意味着数据存储的逻辑顺序会频繁变动)。
    不使用多列主键。
    不使用UUID,MD5,HASH,字符串列作为主键(无法保证主键索引顺序增长,构建索引时为保证索引顺序,会移动大量数据)。
    建议使用自增长id。
    常见索引列建议:
  • 规范:select,update,delete语句的where从句中的列作为索引;
  • 规范:包含在order by、group by、distinct中的字段作为索引;
  • 规范:多表join的关联列作为索引。
    选择索引列的顺序:(从左到右的顺序来使用的)
    区分度最高的列放在联合索引的最左侧;(区分度:select COUNT(DISTINCT column_name)/COUNT(*) from table_name)
    尽量把字段长度小的列放在联合索引的最左侧;
    使用最频繁的列放在联合索引的左侧;
  • 规范:避免建立冗余索引和重复索引。
    说明:
    因为会增加生成查询计划的时间。
    重复索引如primary key(id),index(id),unique index(id)。
    冗余索引如index(a,b,c),index(a,b),index(a)。
  • 规范:对于频繁的查询优先考虑使用覆盖索引。
    说明:
    覆盖索引:包含了所有查询字段的索引。
    好处:避免Innodb表进行索引的二次查找;可以把随机IO变为顺序IO加快查询效率。
  • 规范:尽量避免使用外键。
    说明:尽量避免使用外键约束(写操作效率低,数据完整性建议在业务端实现),但是要在关联键加索引。

4.数据库字段设计规范

(待更新)

5.数据库SQL开发规范

(待更新)

6.数据库操作行为规范

(待更新)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章