MySQL学习笔记_数据库设计规范

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tianmaxingkong_/article/details/80220090
数据库设计的规范:

一.数据库命名规范
二.数据库基本设计规范
三.数据库索引设计规范
四.数据库字段设计规范
五.数据库SQl开发规范
六.数据库操作行为规范


一.数据库命名规范

1.所有的数据库名称和表名称必须使用小写字母并使用下划线分割
  这是因为MySQL数据文件就是Linux下的一个问题,Linux是大小写敏感的,所以MySQL数据库和表的名称也是大小写敏感的:
  Dbname和dbName代表两个不同的数据库
  Table和table代表两个不同的表
  为了不引起奇异,规定数据库名称和表名称必须使用小写字母+下划线的方式

2.所有的数据库名称禁止使用MySQL保留关键字
  select id.username,from,age from tb_user;
  上面的SQL语句有两个from,第一个是字段,第二个是SQL关键字,MySQL在执行查询时,并不能区分是关键字还是数据字段,那么需要:
  select id.username,`from`,age from tb_user;
  需要在from数据字段加反向引号,为了避免出现奇异,禁止数据字段使用SQL关键字。

  MySQL关键字查询:
  http://dev.mysql.com/doc/refman/5.7/en/keywords.html

3.数据库名称命名要见名识意,不要超过32字符

4.临时库表的前缀必须以tmp开头,并以日期为后缀
  备份库表的前缀必须以bak开头,并以日期为后缀

5.所有存储相同数据的列名和列类型必须一致
  e.g.我们在用户信息表和订单表中都会存储用户ID,customer_id,那么要求两个表中用户ID的名称和类型必须一致。
  这样的列一般作为关联列使用,要是数据类型不一致,在进行联合查询的时候,MySQL需要先进行类型转换,有可能导致索引失效,降低查询效率。

二.数据库基本设计规范
1.表引擎使用InnoDB
  在MySQL5.5以前Myisam是默认的存储引擎,MySQL5.5以后InnoDB为默认的存储引擎。
  InnoDB在MySQL5.6及以后进行了很好的优化,InnoDB是一种支持事务、行级锁、有更好的恢复性,高并发下性能更好的存储引擎。

2.数据库和表的字符集统一使用UTF8编码格式
  [说明]UTF8中一个中文字符占3个字节,其他的字符占一个字节。

3.所有的表和字段都需要添加注释 comment

4.尽量控制单表数据量的大小,建议控制在500万以内
  [说明]MySQL在32位操作系统下,单个表的大小是不能超过2G的;
  当数据库数据过大的时候,可以考虑历史数据归档,分库分表的手段来控制数据量的大小。

5.尽量做到冷热数据分离,减小表的宽度
  减小磁盘IO,保证热数据的内存缓存命中率;
  更有效的利用缓存,避免过多的读入无用的冷数据,避免使用select *
  把经常使用的数据放到一个表里面。

6.禁止在表中建立预留字段

7.禁止在数据库中存储图片、文件等二进制的数据

8.禁止在生产环境做数据库压力测试

三.数据库索引设计规范
(建立索引的目的,通过索引查找数据,减少磁盘的随机IO,提高查询的性能)

1.限制每张表的索引个数,建议单张表的索引不超过5个
  索引并不是越多越好,索引可以提高查询效率,同样降低可以降低查询效率,这是因为MySQL在进行查询的时候,会根据现有的索引生产一个最有的查询方案,索引过多导致生成查询方案的时间变长,降低查询的效率;
  索引可以提高查询的效率,但降低了插入、修改数据的效率。

2. InnoDB表必须有一个主键
  InnoDB是一个索引组织表,即数据存储的逻辑顺序和索引顺序是一致的。
  每个表可以有多个索引,但是每个表的存储顺序只有一种,当有多个索引的时候,InnoDB表会按照主键的顺序来进行存储,所以要求每个InnoDB在创建的时候,必须有一个主键,若果没有主键,MySQL就会选择第一个非空唯一索引作为存储顺序,如果没有非空索引的话,MySQL就会自动生成一个6个字节的主键,而自动生成的主键并不是性能最好的。
  【注意】
  (1)InnoDB的主键不能够频繁的变动,这是因为InnoDB是索引组织表,主键的变动会导致表中数据存储的顺序发生改变,影响表的性能。
  (2)主键不建议使用类似UUID,MD5,HASH,字符串作,因为这些值一般无法保证数据的顺序增长。
  以MD5值为列子,我们无法保证后面插入的数据的MD5主键值要比之前数据的MD5值要大,那么存储的时候所以会将其插入到比他大的索引后面,导致大量的数据需要向后移动,造成大量IO操作和占用CPU资源的情况,建议使用MySQL的自增ID作为主键。
  (3)常见的索引建议
    SELECT,UPDATE,DELETE语句的WHERE从句中的列;
    包含ORDER BY,GROUP BY,DISTINCT中的字段;
    多表JOIN的关联列
  (4)对于频繁的查找优先考虑使用覆盖索引;
    InnoDB中主键作为一级索引,当我们按照一个二级索引查找数据的时候,InnoDB首先按照二级索引查找到对应的子节点的位置,而二级索引的子节点中保存的数据是该行主键的信息,要得到真实的数据,还要通过主键进行二次查找,而覆盖索引中,二级索引的键值是可以获得所有数据的,这样避免了进行二次查询。

 四.数据库字段设计规范
  1.优先选择符合存储需求的最小数据类型
    将字符串转化为数字类型进行存储,e.g.将IP地址转化为数字进行存储,MySQL提供了两个函数,在我们存储的时候,调用INET_ATOM('255.255.255.255') = 429****95,将字符串类型的IP地址转换为数字类型,同样在取数据的时候,使用INET_NTOA(429****95) = '255.255.255.255'函数,将数字类型的IP地址还原为字符串

  2.对于非负数据采用无符号整型进行存储
    无符号相对于有符号数据,可以多出一倍的存储空间,e.g.
    SIGNED INT有符int类型的范围在-2147483648到2147483647
    UNSIGNED INT无符int类型的存储范围在0-4294967295之间。

  3.MySQL中的VARCHAR(N)的N代表的是字符数,而不是字节数,这和其他的一些数据库中VARCHAR代表的存储单位不太一样,使用UTF8存储汉字的时候,每个汉字占3个字节。

  4.避免使用TEXT、BLOB数据类型
    建议把BLOB和TEXT列单独分离到扩展表中,TEXT和BLOB只能使用前缀索引

  5.尽可能把所有的列定义为NOT NULL
    索引列为NULL时,需要额外占用 索引空间存储NULL状态;
    进行列的比较和计算时,需要对NULL进行特殊处理,这样有可能导致索引失效

  6.时间日期的存储使用TIMESTAMP或DATETIME类型,不要使用字符串存储
    缺点:无法使用日期函数进行比较;用字符串存储日期占用更多的空间,使用字符串需要使用16字节,要是使用DateType,那么只需要8字节;
    同样的效果TIMESTAMP存储只需要4个字节,而DATETIME需要占用8个字节,但是TIMESTAMP只能存储时间在1970-01-01 00:00:01到2038-01-19 03:14:07之间的时间,TIMESTAMP实质上是使用INT类型来存储数据的,只是在显示的时候,进行转化。

  7.数据库中存储的浮点类型数据包括非精准浮点(float, double)和精准浮点数据类型(decimal)
    约定同财务相关的金额数据,一律使用decimal数据类型;
    decimal数据类型占用的空间是由定义的宽度决定的,每4个字节可以存储9位数字,小数点单独占一个字节;
    decimal数据类型可以用来存储比bigint更大的整数数据,这比使用VARCHAR存储数据更高效

五.数据库SQL开发规范
  1.建议使用预编译语句进行数据库操作
    预编译的SQL语句使用相同的查询计划,节省了MySQL生成查询计划的时间,而且可以防止SQL注入

  2.避免数据类型的隐式转化
    当数据类型不一致的时候,MySQL会进行数据的隐式转换,这会导致建立在列上的索引失效。

  3.充分使用表上已存在的索引
    (1)避免使用双%进行查询,e.g. LIKE '%123%' 或 LIKE '%123'都会导致列上的索引失效,但是使用 LIKE '123%' 的查询方式是可以利用到索引的。
    (2)一个SQL只能利用复合索引中的一列进行范围查找
    如果A、B、C三列进行联合查询,A列进行范围查询,那么B、C上的索引就不会再被用到了,此时我们应该将A列放在联合索引的右侧
    (3)使用left join和not exists来替换not in,后者有可能造成索引失效

   4.禁止使用Select * 进行查询, 应该使用Select <字段名> 进行查询

   5.禁止使用不含字段列名的Insert语句,不应该使用insert into t values(1, 2, 3)这样的语句进行数据插入,而应该使用insert into t(a, b, c) values(1, 2, 3)这样的语句进行插入操作,防止表结构变更造成插入错误。

   6.避免使用子查询,尽量转化为Join查询方式
    子查询无法使用索引;子查询会产生临时表表操作,而这些临时表是没有索引的,会消耗过多的CPU和IO资源。

   7.避免使用JOIN关联过多的表
    每JOIN一个表就会占用一部分内存,MySQL可以通过join_buffer_size设置这部分内存的大小;
    Join操作也会产生临时表操作,影响查询效率;
    MySQL最多允许关联61个表,建议不要超过5个

   8.减少同数据库交互的次数
    数据库更适合处理批量操作,e.g.分页查询的时候,可以一次拉去很多条数据,分批进行返回,而不要分多次每次从数据库中拉去一小部分数据

   9.使用IN代替OR, IN的值不要超过500个
    IN操作可以有效的使用到索引,而OR一般是用不到索引的。

   10.禁止使用order by rand()进行随机排序
    rand()操纵会将所有的符合条件的数据加载到内存中进行排序,这样会消耗大量的CPU和IO资源,我们可以在SQL查询之前生成好随机查找的数据,然后执行SQL进行数据拉取

   11.WHERE从句中禁止对列进行函数转换和计算
    对列进行函数转换和计算,会导致无法使用索引,e.g. 当我们要查询日期的时候,可能使用下面的语句进行查找:
    where date(createTime) = '20180423' 这样,我们便无法使用createTime上的索引,建议使用下面的语句:
    where createTime >= '20180423' and createTime < '20180423' 这样就可以使用createTime的索引了

   12. UNION和UNION ALL的操作,可以合并两个查询的结果集
     当两个结果集之间明显没有重复值的时候,尽量使用UNION ALL,这是因为UNION会将所有的数据放到一个临时表中,然后进行去重操作

    13.拆分复杂的大SQL为多个小SQL进行查询,再合并
      MySQL的一个SQL只能使用一个CPU进行计算,大SQL拆分之后可以通过并行的方式查询,再合并多个结果集,从而提高查询的效率。

六.数据库操作行为规范
  1.超过100w行数据的写操作,要分批进行
    大量的写操作会造成严重的主从延时,造成数据库操作的阻塞;分批进行可以有效的避免大事务操作
    对于大表结构的修改一定要使用pt-online-schema-change这样的工具进行,使用这个工具进行大表结构修改的时候,会首先复制创建一个结构相同的新表,在这个新表的机构上进行修改,再将原表中的数据复制到新表中,同时在原表上添加一些触发器,保证原表中新添加的数据能够及时添加到新表中,在原表中数据全部复制完成之后,会在原表上添加一个很短的时间锁,将新表的名称命名为原表的名称,并将原表删除掉,这样做可以避免大表修改产生的主从延迟的问题,避免在对表字段修改时产生的较长时间的锁表问题。

  2.禁止为程序使用账号授予super权限
      MySQL在达到最大链接数之后,还允许1个具有super权限的用户进行连接,当为前端用户授予super权限之后,DBA处理账号就无法再以super权限进行登录排查问题了,在为程序连接账号授予数据库权限时,应该遵循最小权限的原则,并不能有类似drop table的权限。

猜你喜欢

转载自blog.csdn.net/tianmaxingkong_/article/details/80220090