同一个系统不同表的主键类型应该保持一致
假设某个系统不同模块都有上传文件的功能,文件信息表的rela_id字段表示该文件对应的具体业务id(比如制度附件的rela_id为制度的id),如果业务id又有varchar类型又有int类型,rela_id的类型就很难定义
created_user、created_date、updated_user、updated_date等公共字段命名保持统一
同一个系统,created_user、created_date、updated_user、updated_date等公共字段的命名和类型都应该保持一致,这样可以在工具类用反射统一设置bean的属性。
工具类示例如下
/**
* 设置属性:createUser, createDate
*
* @param obj
*/
public static void setCreateFields(Object obj) {
Class<?> clazz = obj.getClass();
Method setCreateUser = null;;
Method setCreateDate = null;;
try {
setCreateUser = clazz.getMethod("setCreatedUser", String.class);
setCreateDate = clazz.getMethod("setCreatedDate", Date.class);
} catch (NoSuchMethodException | SecurityException e) {
logger.info("反射获取get、set方法失败:", e);
return;
}
try {
setCreateUser.invoke(obj, getUserAccount());
setCreateDate.invoke(obj, new Date());
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
logger.info("调用方法get、set方法失败:", e);
}
}
同一个系统的表字符集保持一致
不同字符集的列在join时,无法使用索引。
比如select * from table_a a, table_b b where a.column_a = b.column_b,如果column_a和column_b的字符集不同,一个为utf8,一个为utf8mb4,无法使用索引
一个系统搭建时应考虑的公共表
系统配置表
用于控制系统的一些配置项(也可以理解为开关),比如某个任务是否开启,是否隐藏某个按钮,等等。
(也可以用配置中心控制,但是比配置中心灵活,本司的配置中心无法实时修改,如果是数据库控制,可以从管理员界面上修改,实时生效)
操作日志表
用于记录用户的操作日志
外部系统请求日志记录表
用于记录与外部系统的请求日志,方便定位问题(shuai guo)
数据字典表
用于定义系统的数据字典,放到同一张表,方便维护,可以从管理员界面修改,实时生效
UUID与自增主键的选择
使用UUID坏处
1.数据量大时读写性能低于自增主键(容易导致innodb页分裂)
2.占用更多存储空间(innodb一个页16k,如果主键占用空间大,一个页能放的记录数就少,会增加IO次数)
使用UUID好处:
1.入库前就知道id
2.无需考虑唯一性问题,但由于性能问题,只适合用于小规模的分布式环境
3.没有规律,安全性高
使用自增主键坏处:
1.入库前获取id比较麻烦(一般ORM框架会提供把id注入bean属性的语法,如mybatis)
2.需要考虑唯一性,如果用于分布式系统,需要设置步长(需要预估业务规模,步长要大于未来最大的集群数)
3.有规律,安全性低(比如接口xxx.com/userInfo?id=12345可以获取到数据,那么暴力尝试xxx.com/userInfo?id=1到xxx.com/userInfo?id=1000000就可能获取到其他数据)
使用自增主键好处:
1.读写性能高
2.占用存储空间小
综上,UUID和自增主键各有利弊,其实除了这两种,还可以选择twitter的snowflake(雪花算法)来生成全局自增主键,同时具备存储空间小,性能高,适用于大规模分布式环境等优点。
中间表
如果需要把其他系统的数据同步到自己的数据库,最好建一张中间表存同步过来的原始数据,而不是直接同步到自己的数据库,原因如下
1.把原始数据落库,方便追溯问题(出了bug,追踪是原始数据的问题还是处理数据出了问题)
2.在中间表加一个字段,标识是否成功同步到自己的数据库,如果失败,用定时任务重试
字段尽量不允许为空
如果字段允许为null,可能会出现诸多问题。
mysql中,null与任何字段(包括自己本身)比较(=或者!=),结果都是false。
例如,想要查出学生中成绩等级不为A的所有学生,select * from student where grade != 'A'
这样的sql,无法查出grade为null的记录,也就是查出的结果比预期的要少。
另外,使用not in时,也可能因为null值丢失数据
设计表时考虑好索引和字段
如果某个表有未提交的事务,此时执行alter语句,会触发MDL(metadata lock,元数据锁),因此设计表时,就要考虑好索引和字段,避免在后期执行alter
网友评论