在项目技术选型时,原则上是选择成熟的平台和技术,同时最好是自己最熟悉的,能做到极致的,用好不用坏,用熟不用生,不然发现问题,你会无从查骑,当然如果你已经有了技术储备,尝鲜未尝不可。
基础规范
- 单表数据量建议控制在 3000 万以内,所有表都需要添加注释,表在设计之初,应该考虑到大致的数据级,若表记录小于1000W,尽量使用单表,不建议分表。
- 主键推荐使用自增列,主键不应该被修改,字符串不应该做主键,如果不指定主键,INNODB 会使用唯一且非空值索引代替,建议使用整型作为主键
- 禁止使用外键,表之间的关联性和完整性通过应用层逻辑来控制
- 不能在数据库中存储图片、文件等大数据
- 非必要不建议保存大字段数据,如需要建议将大字段,访问频率低,或者不需要作为筛选条件的字段拆分到拓展表中,分离冷热数据(做好表垂直拆分)
- 经常需要计算和排序等消耗CPU的字段,应该尽量选择更为迅速的字段,如用TIMESTAMP(4个字节,最小值1970-01-0100:00:00)代替Datetime(8个字节,最小值1001-01-01 00:00:00),通过整型替代浮点型和字符型;变长字段使用varchar,不要使用char
- 存储引擎选择:一般情况可以选择MyISAM存储引擎,如果需要事务支持必须使用InnoDB存储引擎
- 同财务金额相关的数据必须使用 decimal 类型
索引规范
- 唯一索引使用
uniq_[字段名]
来命名 - 非唯一索引使用
idx_[字段名]
来命名 - 不建议在频繁更新的字段上建立索引
- 非必要不要进行
JOIN
,如果要进行JOIN
查询,被JOIN
的字段必须类型相同,并建立索引,不要超过三个表JOIN
。 - 单张表的索引数量建议控制在
5
个以内,索引过多,不仅会导致插入更新性能下降,还可能导致MYSQL的索引出错和性能下降,不要在低基数列上建立索引,例如‘性别’,浪费 - 组合索引字段数量不建议超过
5
个,理解组合索引的最左匹配原则,避免重复建设索引(避免冗余)。比如你建立了(x,y,z)
相当于你建立了(x),(x,y),(x,y,z)
SQL规范
- 尽可能把所有列设定默认值,空字符串或0,不要设定NULL,索引 NULL 列需要额外的空间来保存,所以要占用更多的空间。
- 尽量不要使用
select *
全列查 ,最好是只获取必要字段,select *
会增加cpu/i0/内存、带宽的消耗,可减少表结构变更带来的影响。
insert
必须指定字段,禁止使用insert into Table values()
插入数据,在表结果变更时,能保证对应应用程序无影响。 - 隐私类型转换会使索引失效,导致全表扫描。(比如:手机号码搜索时未转换成字符串)
- 禁止在where后面查询列使用内置函数或者表达式,导致不能命中索引,导致全表扫描.
不推荐:
where date(create_time)='20210000'
推荐:
where create_time >= '20210000' and create_time < '20212000'
- 禁止负向查询(
!=,not like ,no in
等)以及%
开头的模糊查询,造成不能命中索引,导致全表扫描 - 避免直接返回大结果集造成内存溢出,可采用分段和游标方式。返回结果集时尽量使用limit分页显示。
- 尽量在
order by/group by
的列上创建索引。 - 对应同一列进行
or
判断时,使用in
代替or
,In
的值不要超过 500 个,in
操作可以更有效的利用索引,or
大多数情况下很少能利用到索引。
关系型数据库设计:三大范式
第一范式: 要求数据库表的每一列都是不可分割的原子数据项。
第二范式: 在第一范式的基础上,需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关
第三范式: 在第二范式的基础上,需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
打破范式标准:
建议建表的时候,就把这些列放在一个表里,比如一开始有student(id, name),class(id, description),student_class(student_id, class_id)三张表,这样是符合数据库范式的(第一范式,第二范式,第三范式,BC范式等),没有任何冗余,但是马上就不符合“编程规范“了,那我们可以用一张大表代替它,student_class_full(student_id, class_id, name, description),这样name和description可能要被存储多份,但是由于不需要join了,查询的性能就可以提高很多了。
任何的规范都是在特定情况下的某种妥协,脱离了这个环境,就不一定成立了。
需要说明的是,这种脱离范式的设计,是互联网业务在设计高并发表时惯用的做法。
表的拆分
- 垂直拆分
将一个属性过多的表,一行数据较大的表,将不同的属性分割到不同的数据库表中。以降低单库表的大小,把有关联但是独立的数据拆分为两个表,如用户表和部门表。
特点:
每个表的结构不一致
每个表的数量都是全量
表和表之间一定会有一列会进行关联,一般都是主键
原则:
将长度较短,访问频率较高的字段放在一个表中,主表
将长度较长、访问频率比较低的字段放一个表中
将经常访问字段放一个表中。
所有表的并集是全量数据。
- 水平拆分
单表数据过大,IO瓶颈限制查询速度,对表进行水平拆分(也就是我们说的:分表),比如根据时间维度分表。
大数据表添加字段需要注意
在开发时,有时需要给表加字段,在大数据量且分表的情况下,怎么样稳定的添加。
1:直接alter table add column,数据量大时不建议,(会产生写锁)
alter table ksd_user add column api_pay_no varchar(32) not null comment '用户扩展订单号'
alter table ksd_user add column api_pay_no varchar(32) not null unique comment '用户扩展订单号'
2:提前预留字段(不优雅:造成空间浪费,预留多少很难控制,拓展性差)
3:新增一张表,(增加字段),迁移原表数据,在重新命名新表作为原表。
4:放入extinfo(无法使用索引)
5: 提前设计,使用key/value方法存储,新增字段时 ,直接加一个key就好了(优雅)
网友评论