Mysql数据库设计原则

1. 核心原则

不在数据库做运算

CPU计算务必移至业务层

控制列数量(字段少而精,字段数建议在20以内)

平衡范式与冗余(效率优先;往往牺牲范式)

拒绝3B(拒绝大SQL语句:big sql, 拒绝大事务:big transaction,拒绝大批量:big batch)

2. 字段类原则

用好数值类型(用合适的字段类型节约空间)

字符转化为数字(能转化的最好转化,同样的节约空间,提高查询性能)

避免使用NULL字段(NULL字段很难查询优化,NULL的索引需要额外的空间,NULL字段的复合索引无效)

少用text类型(使用varchar代替text)

3. 索引类原则

合理使用索引(改善查询,减慢更新,索引一定不是越多越好)

字符字段必须建前缀索引

不在索引做列运算

innodb主键推荐使用处境列(主键建立聚簇索引,主键不应该被修改,字符串不应该做主键)理解InnoDB索引保存结构就知道了)

不使用外键 (由程序保证约束)

说到不用外键,我人都傻了。有些功能是基于外键做的,其实在很多时间插入的时候也是有非常多的问题。

4. SQL类原则

sql语句尽可能的简单(一条sql只能在一个CPU运算,大语句拆小语句,减少锁时间,一条大SQL可以堵死整个库)

简单的事务

避免使用 trig/func(触发器、函数不用客户端程序取而代之)

不使用select * (消耗cpu,io内存,带宽,这种程序不具有扩展性)

OR改写为IN(or 的效率是N级别)

OR改写为UNION(mysql的索引合并很弱智)

select id from t where phone ='159'  or name = 'john';

=>

select id from t where phone = '159'

union

select id from t where name = 'john'


避免负向 %

慎用count(*)

limit 高效分页,limit值越大,效率越低

使用union all替代 union (union有去重开销)

少用连接join

使用group by

请使用同类型比较

打散批量更新



小结:

可能没有做过开发的看的时候是看不怎么懂的,这些话都是非常的精练,这些细节也决定了你的程序的响应时间。


5. 数据类型的选择

数据类型的选择,重点在于合适二字,如何确定选择数据类型是否合适

  1. 使用可以存下你的数据的最小的数据类型。(时间类型数据:可以使用varchar类型,可以使用int类型, 也可以使用时间戳类型)

  2. 使用简单的数据类型,int要比varchar类型在mysql处理上简单。(int 存储时间是最好的选择)

  3. 尽可能的使用not null定义字段(Innodb 的特性所决定,非not null值,需要额外的在字段存储,同时也会增加IO和存储的开销)

  4. 尽量少用text类型,非用不可时最好考虑分表。


这里还讲了一个案例,存储IP时不要用字符串,而是要用bigint,可以省几个字节,用 INET_ATON(), INET_NTOA(),存时间也是直接存时间戳。

因为数据太少看不出区别,如果字段多了,数据量上千万,那么数据库就可可能多出几个GB的空间。

6. 垂直拆分原则

通常垂直拆分可以按以下原则进行:

  1. 把不常用的字段表单独存放到一个表中

  2. 把大字段独立存放到一个表中

  3. 把经常一起使用的字段放到一起

7. 水平拆分

表的水平拆分为了解决单表数据量过大的问题,水平拆分的表每一个的结构都是完全一致的

水平不拆分,如果单表数据量达到上亿条,那么这时候我们尽管加了完美的索引,查询效率低,写入的效率也相应降低。

方法:

  1. 对customer_id进行hash运算,如果要拆分为5个表则使用mo(customer_id,5)取出0-4个值

  2. 针对不同的hashId把数据存储到不同的表中

8. 水平拆分面临的挑战

  1. 跨分区表进行数据查询

    • 业务上给不同的用户返回不同的业务信息,对分区表没有大的挑战

    • 前端业务统计:

  2. 统计及后台报表操作


    • 但是对后台进行报表统计时,数据量比较大,后台统计时效性比较低,后台就用汇总表,前后台的表拆分开



发表评论: