1.建表规约
目的:解决数据库取名的难题,给字段选择合适的类型和长度信息
1.表字段命名
- 字段名称必须是小写字母或者数字以及下划线。
- 禁止以数字为字段的开头。错误示例:
1Name。 - 禁止两个下划线中间只出现数字。错误示例:
a_1_b。 - 不可使用复数名词。比如:
customer不要写成customers。 - 禁用保留字。比如:
desc, order。 - 表示是否概念的字段,必须使用
is_xx的写法。比如:is_delete。
2.数据类型的选择
- 小数类型使用:
decimal。 - 货币数据使用最小货币单位。数据类型使用
bigint。 - 如果一个字段的内容是固定的长度,要使用
char。原因是会节约两个字符的空间,但是如果长度不一样不要使用char,这样长度小的字段取出来的数据会被自动填充,要使用trim才行。 varchar的长度最好不要超过5000。如果超过了,推荐使用text,longtext,blob等,而且这里有个细节,如果一个字段的长度够长,推荐使用另外一个表存储这些信息,可以提高查询的效率。
3.表的设计
- 所有的表必备三字段
id
create_time
update_time
- 表名:业务名称_表的作用
- 库名应与应用名称尽量保持一致。例如:用户信息的库:使用
user。 - 如果某个字段表示的是状态,那么在新增了新的状态后,需要及时更新该字段的注释。
- 字段允许一定程度上的荣誉,以提高性能。但是这里得考虑数据的一致性。
- 单行表的行数超过500万行,或者是数据库的容量超过了2GB才推荐进行分库分表,不然没必要进行分库分表。。
2.索引规约
合理的分析和使用索引,是提高查询效率的有效手段。
1.索引的分类
1.按索引的特性
- 持久性。索引会被持久化进入磁盘。
- 有序性。索引是有序的,方便数据的查询。
2.按存储形式
- 聚簇索引
- 非聚簇索引
3.按索引的数量
- 单列索引
- 组合索引
4.innoDB索引相关
- 可以创建
- 主键索引
- 唯一索引
- 普通索引
- 不可创建
- 覆盖索引
2.索引的数据结构
1. 演变路线
由二叉查找树->平衡二叉树->btree->b+tree
可模拟以上数据接口的存储行为的网站: www.cs.usfca.edu/~galles/vis…
3.索引的命名
- 主键索引:
pk_字段名 - 主键索引:
uk_字段名 - 主键索引:
idx_字段名
4.建索引规约
- 有唯一特性的字段比如加上索引。
- 在
varchar字段上面建立索引,必须指定其长度。 - 建立组合索引时,区分度最高的要在组合索引为的左边。比如
idx_name_age (name,age)。
5.谨防误解
- 宁缺毋滥。避免一个查询就搞一个索引,所以也是需要占空间的,不要建立不必要的索引。
- 吝啬创建索引。任务索引会占用空间,所以不去创建索引,导致效率低下哎。
- 抵制唯一索引。认为唯一约束在代码层面做判断就可以了,先查后插。
3.SQL和ORM映射规约
1.SQL的优化
- 注意字段类型。防止因为类型不同造成隐式转换,导致索引的失效。
- 利用覆盖索引来进行查询,避免回表。
辅助索引的回表:辅助索引底层数据接口的叶子节点存储的是主键信息。所以辅助索引的查询逻辑为,先通过辅助索引查询到了主键,然后通过主键去查询对应的数据。这样就造成了两次IO操作,这就叫回表。覆盖索引:在查询的时候,返回的值都是有索引的值,这样就可以直接在索引里面找到对应的值。就不需要回表这一步操作了。
- 利用有序性。如果有
order by的场景下,要注意索引。因为不加索引的时候,会使用到filesort文件排序,这样的效率是很低的。所以可以通过加索引来避免文件排序。 - 尽量少用左模糊和全模糊匹配。如果实在要用,可以考虑走搜索引擎。
2.SQL避坑指南
- 不用使用外键和级联的关系。所有的外键都在代码服务层去解决。
- 禁止使用存储过程,因为很难调试和拓展,几乎不能维护。
- 数据订正修改时,要先
select,避免出现误删除的情况。 - 只要涉及到多个表的查询,都要使用别名。
- 所有的别名前都要加上
as,方便查看。比如:t1,t2...。 in后面的集合数量要限制在1000以内。
3.Explain的使用
- type的优先级,由好到差
system > const > eq_ref > ref > range > index > ALL - 一个查询的type至少要达到range类别
- 一个比较详细的介绍网站:www.cnblogs.com/clphp/p/540…
4.ORM映射规约
- 在表查询中,一律不要用
*作为查询的字段列表。 - POJO的布尔属性不能为
is(因为有些工具或者框架会对is做处理,容易踩坑)。而数据库的字段必须得加is_。 - 查询的返回结果要用ResultMap映射,不能使用HashMap和HashTable作为结果集。
- 不能使用
${}作为替换符。会由sql注入危险。 - 不要使用
mybatis自带的queryForList方法。因为该方法的底层是把所有的数据都取出来,在内存里面做裁剪操作。 - 做数据更新的时候,一定要更新
update_time字段。 - 不要写一个很大的
update方法,容易出问题。应该要修改什么就写什么。
4.实战
实战要严格遵循三大范式
1.第一范式:每列的属性不可拆分
如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
2.第二范式:表中的每列都和主键相关
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
3.第三范式:每列都和主键直接相关,而不是间接相关
比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。