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. 数据类型的选择
数据类型的选择,重点在于合适二字,如何确定选择数据类型是否合适
使用可以存下你的数据的最小的数据类型。(时间类型数据:可以使用varchar类型,可以使用int类型, 也可以使用时间戳类型)
使用简单的数据类型,int要比varchar类型在mysql处理上简单。(int 存储时间是最好的选择)
尽可能的使用not null定义字段(Innodb 的特性所决定,非not null值,需要额外的在字段存储,同时也会增加IO和存储的开销)
尽量少用text类型,非用不可时最好考虑分表。
这里还讲了一个案例,存储IP时不要用字符串,而是要用bigint,可以省几个字节,用 INET_ATON(), INET_NTOA(),存时间也是直接存时间戳。
因为数据太少看不出区别,如果字段多了,数据量上千万,那么数据库就可可能多出几个GB的空间。
6. 垂直拆分原则
通常垂直拆分可以按以下原则进行:
把不常用的字段表单独存放到一个表中
把大字段独立存放到一个表中
把经常一起使用的字段放到一起
7. 水平拆分
表的水平拆分为了解决单表数据量过大的问题,水平拆分的表每一个的结构都是完全一致的
水平不拆分,如果单表数据量达到上亿条,那么这时候我们尽管加了完美的索引,查询效率低,写入的效率也相应降低。
方法:
对customer_id进行hash运算,如果要拆分为5个表则使用mo(customer_id,5)取出0-4个值
8. 水平拆分面临的挑战
跨分区表进行数据查询
业务上给不同的用户返回不同的业务信息,对分区表没有大的挑战
前端业务统计:
统计及后台报表操作
但是对后台进行报表统计时,数据量比较大,后台统计时效性比较低,后台就用汇总表,前后台的表拆分开