1. 为什么要数据库设计
我们在设计数据表的时候,要考虑很多问题。比如:
~ 用户都需要什么数据?需要在数据表种保存那些数据?
~ 如何保证数据表中的数据正确性,当插入,删除,更新的时候改进型怎样的 约束检查?
~ 如何降低数据表的 数据冗余度,保证数据表不会因为用户的增长而迅速扩张?
~ 如何让负责数据库维护的人员 更方便 的使用数据库?
~ 使用数据库的应用场景也各不相同,可以说针对不同的情况,设计出来的数据表可能千差万别。
现实情况中,面临的场景:
当数据库运行了一段时间后,我们才发现数据表设计的有问题。重新调整数据表的结构,就需要做数据迁移,还有可能影响程序的业务逻辑,以及网站正常的访问。
如果是糟糕的数据库设计可能会造成以下问题:~ 数据冗余,信息重复,存储空间浪费。
~ 数据更新,插入,删除的异常。
~ 无法正确表示信息。
~ 丢失有效性
~ 程序性能差
良好的数据库设计则有以下优点:~ 节省数据的存储空间
~ 能够保证数据的完整性
~ 方便进行数据库应用系统的开发
总之,开始设计数据库的时候,我们就需要重视数据表的设计。为了建立 冗余较小,结构合理 的数据库,设计数据库时必须遵循一定的规则。
2. 范式
2.1 范式简介
在关系型数据库种,关于数据表设计的基本远着呢,规则就称为范式。可以理解为,一张数据表的设计结构需要满足的某种你设计标准的级别。要想设计一个结构合理的关系型数据库,必须满足一定的范式。
范式的英文名称时Normal Form,简称NF。他是英国人E.F.Codd在上个世纪70年代提出的关系型数据库模型后总结出来的。范式是关系型数据库理论的基础,也是我们在设计数据库结构过程中所要遵循的规则和指导方法。
2.2 范式都包括哪些
目前关系型数据库有六种常见范式,按照范式级别,从低到高分别是:第一范式(1NF),第二范式(2NF),第三范式(3NF),巴斯-科德范式(BCNF),第四范式(4NF),第五范式(5NF,又称完美范式)。
数据库的范式设计越高阶,冗余度就越低,同时高阶的范式一定符合低阶范式要求,满足最低要求的范式是第一范式。在第一范式的基础上满足更多规范要求的称为第二范式,其余范式一次类推。
一般来说,在关系型数据库设计中,最高也就遵循到BCNF,普通还是3NF.但也不是绝对,有的时候为了提高某些查询性能,我们还需要破范式规则,也就是反范式化。
2.3 键和相关属性的概念
范式的定义会使用到主键和候选键,数据库中的键(key)有一个或者多个属性组成。数据表种常用的几种键和属性的定义:
~ 超键:能为一标识元组的属性集叫做超键。
~ 候选键:如果超键不包括多余的属性,那么这个超键就是候选键。
~ 主键:用户可以从候选键中选择一个作为主键。
~ 外键:如果数据表R1中的某属性集不是R1的主键,而是另一个数据表R2的主键,那么这个属性集就是数据表R1的外键。
~ 主属性:包含在任一候选键中的属性称为主属性。
~ 非主属性:与主属性相对,指的是不包含在任何一个候选键中的属性。
通常,我们可将候选键称为“码”,把主键也成为“主码”。因为键可能是由多个属性组成的,针对单个属性,我们还可以用主属性和非主属性来进行区分。
举例:这里有两个表:
球员表(player):球员编号 | 姓名 | 身份证号 | 年龄 | 球队编号
球队表(team):球队编号 | 主教练 | 球队所在地
~ 超键:对于球员表来说,超键就是包括球员编号或者身份证号的任意组合,比如(球员编号)(球员编号,姓名)(身份证号,年龄)等。
~ 候选键:就是最小的超键,对于球员表来说,候选键就是(球员编号)或者(身份证号)。
~ 主键:我们自己定,也就是从候选键中选择一个,比如(球员编号)。
~ 外键:球员表中的球队编号
~ 主属性,非主属性:在球员表中,主属性是(球员编号)(身份证号),其他的属性(姓名)(年龄)(球队编号)都是非主属性的。
2.4第一范式(1NF)
第一范式主要是确保数据表中每个字段值必须具有原子性,也就是说数据表中每个字段的值为 不可再次拆分 的最小数据单元。
我们在设计某个字段的时候,对于字段x来说,不能把字段x拆分称字段x-1和字段x-2。事实上,任何DBMS都会满足第一范式的要求,不会讲字段进行拆分。
举例1:假设一家公司要存储员工的姓名和联系方式。他创建要给如下表:
emp_id emp_name emp_address emp_mobile 101 zhangsan beijing 7897978979 102 lisi shanghai 7897978972
7897978974
103 wangwu liaoning 7897978973 104 zhaoliu shanghai 7897978975
7897978976
该表不符合1NF,因为规则说了“表的每个属性必须具有原子值”,lisi和zhaoliu员工的emp_mobile值违反了该规则。为了使表符合1NF,我们应该有如下表数据:
举例2:
user 表的设计不符合第一范式
其中,user_info字段为用户信息,可以进一步拆分成更小粒度的字段,不符合数据库设计对第一范式的要求。将user_info拆分后如下: 举例3:
字段名称 字段类型 是否是主键 说明 id int 是 主键id username varchar(30) 否 用户名 password varchar(50) 否 密码 user_info varchar(255) 否 用户信息(包含真实姓名,电话,住址)
属性的原子性是 主观的。例如Employees关系中雇员姓名应当使用1个(fullname),2个(firstname和lastname)还是3个(firstname,middlename和lastname)属性表示呢?答案取决于应用程序。如果应用程序需要分别处理雇员的姓名部分(搜索使用),则有必要把他们分剋。否则,不需要。
表1:表2:
姓名 年龄 地址 张三 20 广东省广州市三元里78号 李四 24 广东省深圳市龙华新区
2.5 第二范式
第二范式要求,在满足第一范式的基础上,还需要满足数据表里的每一条数据记录,都是可唯一标识的。而且所有非主键字段,都必须完全依赖主键,不能只依赖主键的一部分。如果知道主键的所有属性的值,就可以检索到任何元组的任何属性的任何值。(要求中的主键,其实可以拓展替换为候选键)。
举例1:
成绩表(学号,课程号,成绩)关系中,(学号,课程号)可以决定成绩,但是学号不能决定成绩,课程号也不能决定成绩,所以(学号,课程号)才能确定成绩就是 完全依赖关系。
举例2:比赛表,里面包含球员编号,姓名,年龄,比赛编号,比赛时间和比赛场地等属性,这里候选键和主键都为(球员编号,比赛编号),我们可以通过候选键(或主键)来决定如下的关系:
(球员编号,比赛编号)-> (姓名,年龄,比赛时间,比赛场地,得分)
但是这个数据表不满足第二范式要求,因为数据表中的字段之间还存在着如下的对应关系:
(球员编号)-> (姓名,年龄)
(比赛编号)-> (比赛时间,比赛场地)
对于非主属性来说,并非完全依赖候选主键。这样会产生怎样的问题?
1. 数据冗余:如果一个球员可以参加m场比赛,那么球员的姓名和年龄就重复了m-1次。一个比赛也可能会有n个球员参加,比赛的时间和地点就重复了n-1次。
2. 插入异常:如果我们想要添加一场新的比赛,但是这时还没有确定参加的球员都有谁,那么就没办法插入。
3. 删除异常:如果我要删除某个球员编号,如果没有单独保存比赛表的话,就会同时把比赛信息删除掉。
4. 更新异常:如果我们调整了某个比赛的时间,那么数据表中所有这个比赛的时间都需要进行调整,否则就会出现异常比赛时间不同的情况。
为了避免出现上述的情况,我们可以把球员比赛表设计为下面的三张表。
表名 属性(字段) 球员player表 球员编号,姓名和年龄 比赛game表 比赛编号,比赛时间和比赛场地 球员比赛关系player_game表 球员编号,比赛编号和得分属性 这样的话,每张数据表都符合第二范式,也就避免了异常情况发生。
1NF告诉我们字段属性需要是原子性的,而2NF告诉我们每一张表就是一个独立的对象,一张表只表达一个意思。
举例3:定义一个名为Orders表,表示订单和订单行的信息:
违反了第二范式,因为有非主键属性仅仅依赖于候选键(或主键)的一部分。例如,可以仅通过orderid找到订单的orderdate,以及 customerid 和 companyname,而没有必要再去使用 productid。
修改:
orders表和orderdetails表如下,此时符合第二范式
小结:第二范式要求实体的属性完全依赖主关键字。如果存在不完全依赖,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新的实体鱼元实体之间是一对多的关系。
2.6 第三范式
第三范式是在第二范式的基础上,确保数据表中每一个非主键字段都和主键字段直接相关,也就是说,要求数据表中的所有非主键字段不能依赖于其他非主键字段。(即,不能存在非主属性A依赖于非主属性B,非主属性B依赖于主键C的情况,即存在A->B->C的决定关系)通俗的讲,该规则的意思是所有 非主键属性 之间不能有依赖关系,必须相互独立。
这里的主键可以拓展为候选键。
举例1:
部门信息表:每个部门由部门编号,部门名称,部门简介等信息。
员工信息表:每个员工有员工编号,姓名,部门编号。列出部门编号后就不能再将部门名称,部门简介等部门有关的信息再加入员工信息表中。
如果不存在部门信息表,则根据第三范式也应该构建它,否则就会有大量的数据冗余。
举例1:
字段名称 字段类型 是否是主键 说明 id int 是 商品主键id category_id int 否 商品类别id category_name varchar 否 商品类别名称 goods_name varchar 否 商品名称 price decimal 否 商品价格 商品类别名称依赖于商品类别编号,不符合第三范式。
修改:
表1:符合第三范式的 商品类别表 的设计
字段名称 字段类型 是否是主键 说明 id int 是 商品类别主键id category_name varchar 否 商品类别名称 表2:符合第三范式设计的 商品表 设计
字段名称 字段类型 是否是主键 说明 id int 是 商品主键id category_id varchar(30) 否 商品类别id goods_name varchar(30) 否 商品名称
price dicimal(10,2) 否 商品价格 商品表goods通过商品类别id字段(category_id)与商品类别goods_category进行关联。
举例3:
球员player表:球员编号,姓名,球队名称和球队主教练。现在,我们把属性之间的依赖关系画出来,如下图所示:
你能看到球员编号决定了球队名称,同时球队名称决定了球队主教练,非主属性球队主教练就会传递依赖于球员编号,因此不符合3NF要求。
符合3NF后的数据模型通俗的讲,2NF和3NF通常以这句话概括:“每个非键属性依赖于键,依赖于整个键,并且除了键别无他物”。
2.7小结
关于数据表的设计,有三个范式要遵循。
1. 第一范式,确保每列保持 原子性
数据库的每一列都是不可分割的原子数据项,不可再分的最数据单元,而不能是集合,数组,记录等非原子数据项。
2. 第二范式,确保每列都和主键 完全依赖
尤其是在复合主键的情况下,非主键部分不应该依赖于部分主键。
3. 第三范式确保每列都和主键列 直接相关,而不是间接相关
范式的优点:数据的标准化有助于消除数据库中的 数据冗余,第三范式通常被认为在性能,扩展性和数据完整性方面达到了最好的平衡。
范式的缺点:范式的使用,可能 降低查询的效率。因此范式等级越高设计出来的数据表就越多,越精细,数据的冗余度就越低,进行数据查询的时候就可能需要 关联多张表,这不但代价昂贵,也可能是一些 索引策略失效。
范式本身没有优劣之分,只有适合场景不同。没有完美的设计,只有合适的设计,我们在数据表的设计中,还需要根据需求将凡是反范式混合使用。
3. 反范式化
3.1 概述
有的时候不能简单按照规范要求设计数据表,因为有的数据看似冗余,其实对业务来说十分重要。这个时候,我们就要遵循 业务优先 的原则,首先满足业务需求,在尽量减少冗余。
如果数据库中的数据量比较大,系统的UV和PV访问频次比较高,则完全按照mysql的三大范式设计数据表,读数据时会产生大量的关联查询,在一定程度上会影响数据库的读取性能。如果我们想对查询效率进行优化,反范式化 也是一种优化思路。此时,可以通过在数据表中 增加冗余字段 来提高查询效率。
规范化 VS 性能1. 为满足某种商业目标,数据库性能比规规范化数据库更重要
2. 在数据规范化的同时,要综合考虑数据库的性能
3. 通过在给定的表中添加额外的字段,以大量减少需要从搜索信息所需的时间
4. 通过在给定的表中插入计算列,以方便查询
3.2 应用举例
举例1:
员工的信息存储在 employess 表中,部门信息存储在 departments 表中。通过 employess 表中的 department_id 字段鱼 departments 表建立关联关系。如果要查询一个员工所在的部门名称:
select employess_id, department_name from employess e join departments d on e.department_id = d.department_id;
如果经常需要进行这个操作,连接查询就会浪费很多时间。可以在employess表中增加一个冗余字段 department_name,这样就不用每次都进行连接操作了。
举例2:反范式化的 goods商品信息表 设计如下:
字段名称 字段类型 是否时主键 说明
id int 是 商品id category_id varchar 否 商品类别id category_name varchar 否 商品类别名称 goods_name varchar 否 商品名称 price decimal 否 商品价格 举例3:
我们有2个表,分别是 商品流水表 和商品信息表。商品流水表里有400万条流水记录,商品信息表里有2000条商品记录。
商品流水表:
商品信息表:
两个表是符合第三范式的要求。但是,在我们项目的实施过程中,对流水的查询频率很高,而且为了获取商品名称,基本都会用到与商品信息表的连接查询。
为了减少连接, 我们可以直接把商品名称字段加到流水表里。这样一来我们就可以直接从流水表中获取商品的名称字段了。虽然增加了冗余字段,但是避免了关联查询,提升了查询效率。
新的商品流水表如下所示:
3.3 反范式化的新问题
反范式化可以通过空间换时间,提升查询效率,但是反范式化也会带来一些新问题:
~ 存储空间变大了。
~ 一个表中字段做了修改,另一个表中冗余的字段也必须同时修改,否则数据不一致。
~ 若采用存储过程中来支持数据的更新,删除等额外操作,如果更新频繁,会非常消耗系统资源
~ 在数据量小的情况下,反范式不能体现性能的优势,可能还会让数据库的设计更加复杂
3.4 反范式化的使用场景
当冗余信息有价值或者能 大幅度提高查询效率 的时候,我们才采用范式化的优化。
1. 增加冗余字段的建议
增加冗余字段一定要符合如下两个条件。只有满足这两个条件,才可以考虑增加冗余字段。
~ 这个冗余字段 不需要经常进行修改。
~ 这个冗余字段 查询的时候不可或缺。
2. 历史快照,历史数据的需要
在现实生活中,我们经常需要一些冗余信息,比如订单中的收货人信息,包括姓名,电话和地址等。每次发生的 订单收货信息 都属于 历史快照,需要进行保存,单用户可以随时修改自己的信息,这是保存这些冗余信息是非常有必要的。
反范式化优化也常用在 数据仓库 的设计中,因为数据仓库通常 存储历史数据,对增删改的实时性要求不高,对历史数据的分析需求强。这是适当允许数据的冗余度,更方便进行苏韩剧分析。
我简单总结下数据仓库和数据库在使用上的区别:
1. 数据库设计的目的在于 捕获数据,而数据仓库设计的目的在于 分析数据;
2. 数据库对数据的 增删改实时性 要求强,需要存储在线的用户数据,而数据仓库存储的一般是历史数据;
3. 数据库设计需要 尽量避免冗余, 但是为了提高查询效率也允许一定的 冗余度,而数据仓库在设计上更偏向采用反范式化设计。
7. 实战案例
商超进货系统中的 进货单表 进行剖析:
进货单表:
这个表中的字段很多,表里的数据量也很惊人。大量重复导致表变得异常庞大,效率极低。如何改造?
在实际工作场景中,这种由于数据表结构设计不合理,而导致的数据重复的现象并不少见。往往是系统虽然能够运行,承载能力却很差,稍微优点流量,就会出现内存不足,cpu使用率飙升的情况,甚至会导致整个项目失败。
7.1 迭代1次:考虑1NF
第一范式要求:所有的字段都是基本数据字段,不可进一步拆分。这里需要确认,所有的列中每个字段只包含一种数据。
这张表里,我们把property这个字段,拆分成 specification 规格 和 unit 单位,这2个字段如下:
7.2 迭代2次:考虑2NF
第二范式要求,在满足第一范式的基础上,还需要满足数据表里的每一条胡数据记录,都是可唯一标识的。而且所有字段,都必须完全依赖主键,不能只依赖主键的一部分。
第一步,就是要确定这个表的主键。通过观察发现,字段 listnumber 单号 + barcode 条码 可以唯一标识每一条记录,可以作为主键。
第二步,确定好了主键以后,判断啊那些字段完全依赖主键,哪些字段只依赖于主键的一部分。把只依赖于主键的一部分的字段拆分出去,形成新的数据表。首先,进货单明细表里面的 goodsname名称 specification 规格 unit 单位这些信息是商品的属性,只依赖于barcode条码,不完全依赖主键,可以拆分出去。我们把这三个字段加上它们所依赖的字段barcode条码,拆分形成一个新的数据表 商品信息表。
这样一来,原来的数据表就被拆分成了两个表。
商品信息表:
进货单表:
此外,字段supperlierid, supperliername,stock 只依赖于listnumber单号,不完全依赖于主键,所以我们可以把supplierid,suppliername,stock这三个字段拆除去,再加上它们依赖的字段listnumber,就形成了一个新的表 进货单头表。剩下的字段,会组成新的表,我们叫他进货单明细表。
原来的数据表就拆分成了3各表。
进货单头表:
进货单明细表:
商品信息表:
现在,我们再来分析一下拆分后的3个表,保证这3各表都满足第二范式要求。
第三步,在商品信息表中,字段barcode是有可能重复的,比如,用户门店可能有散装称重商品和自产商品,会存在条码共用的情况。所以,所有的字段都不能唯一标识表里的记录。这个时候,我们必须给这个表加上一个主键,比如说是 自增字段 itemnumber 。
现在,我们就可以把进货单明细表里面的字段barcode都替换成字段itemnumber,这就得到了新的如下表。
进货单明细表:
商品信息表:
拆分后的3个数据表就全部满足了第二范式的要求。
7.3 迭代三次:考虑3NF
我们的进货单头表,还有数据冗余的可能。因为suppliername依赖supplierid,那么这个时候就可以按照第三范式的原则进行拆分了。我们就进一步进行拆分下进货单头表,把他拆解成供货商表和进货单头表.
供货商表:
进货单头表:
这2个都满足第三范式的要求了。
7.4 反范式化:业务优先原则
在进货单明细表中,quantity * importprice = importvalue, importprice, quantity 和importvalue这三个字段,可以通过任意两个计算出第三个来,这就存在冗余字段。如果严格按照第三范式的要求,现在我们应该进行进一步优化。优化的办法是删除其中一个字段,只保留另外两个,这样就没有冗余数据了。
可是,真的可以这样做吗?要回答这个问题,我们就要先了解下实际工作中的 业务优先原则。
所谓的业务优先原则,就是指一切以业务需求位置,技术服务于业务。完全按照理论的设计不一定就是最优,还要根据实际情况来决定。这里我们就来分析下不同选择的利与弊。
对于quantity * importprice = importvalue , 看起来 importvalue 似乎是冗余字段,但并不会导致数据不一致。可是如果我们把这个字段取消,是会影响业务的。
因为有的时候,供货商会经常进行一些促销活动,按金额促销,那他们拿来的进货单只有金额,没有价格。
而 importprice 反而是通过 importvalue / quantity 计算出来的,经过四舍五入,会产生较大的误差。这样日积月累,最终稿会导致查询结果出现较大的偏差,影响系统的可靠性。
举例:进货金额importvalue是25.5元,数量是34,那么精活价格importprice就等于25.5/ 34= 0.74元,但是如果用这个是计算出来了进货价格importprice来计算进货金额,那么进货金额就等于0.74*34=25.16元,其中相差了25.5-25.16=0.34元。所以,本着业务优先的原则,在不影响系统可靠性的前提下,数据冗余,保留了importvalue importpirce quantity。
因此,最后我们可以把进货单表拆分成下面的4个表:供货商表:
进货单头表:
进货单明细表:
商品信息表:
这样一来,我们避免了冗余数据,而且还能够满足业务的需求,这样的数据表设计,才是合格的设计。
9.数据表的设计原则
1. 数据表的个数越少越好
RDBMS 的核心在于对实体和联系的定义,也就是ER模型,数据表越少,证明实体和联系设计的越简洁,即方便理解又方便操作。
2. 数据表中的字段个数越少越好
字段个数越多,数据冗余的可能性越大。设置字段个数少的前提是各个字段相互独立,而不是某个字段的取值可以由其他字段计算出来。当然字段个数少是相对的,我们通常会在数据冗余和检索效率进行平衡
3. 数据表中联合主键的字段个数越少越好
设置主键是为了确定唯一性,当一个字段无法确定唯一性的时候,就需要采用联合主键的方式。联合主键中的字段越多,占用的索引空间就越大,不仅会加大理解难度,还会增加运行时间和索引空间,因此联合主键的字段个数越少越好。
4. 使用主键和外键越多越好
数据库的设计实际上就是定义各种表,以及各种字段之间的关系。这些关系越多,证明这些实体之间的冗余度越低,利用度越高。这样做的好处在于不仅保证了数据表之间的独立性,还能提升相互之间的关联使用率。
三少一多的原则的和兴就是 简单可复用,简单指的是用更少的表,更少的字段,更少的联合主键字段来完成数据表的设计。可复用则是通过主键,外键的使用来增强数据表之间的复用率。因为一个主键可以理解是一张表的代表。键设计的越多,证明它们之间利用率越高。
10. 数据库对象编写建议
前面我们讲了数据库的设计规范,下面给出的这些规范适用于大多数公司,按照下面的规范来使用数据库,这样数据库可以发挥出更高的性能。
10.1 关于库
1. 【强制】哭的而名称必须控制在32个字符以内,只能使用英文字母,数字和下划线,建议以英文字母开头。
2.【强制】数据库中英文一律小写,不同单词采用下划线分割。必需见名之意。
3.【强制】库的名称格式:业务系统名称_子系统名。
4.【强制】库名禁止使用关键字
5.【强制】创建数据库时必须 显示指定字符集,并且字符集只能指定utf8或utfmb4
6.【建议】对于程序连接数据库账号,遵循 权限最小的原则。
7.【建议】临时库以tmp_ 为前缀,并以日期后缀;
备份库以bak_为前缀,并以日期为后缀;
10.2 关于表, 列
1.【强制】表和列的名称必须控制在32个字符以内你,表名只能使用英文字母,数字和下划线,建议以英文字母开头。
2.【强制】表名、列名一律小写,不同单词采用下划线分割。须见名之意。
3.【强制】表名要求有模块名强相关,同意模块的表名尽量使用统一前缀
4.【强制】创建表时必须 显式指定字符集 为utf8或utfmb4
5.【强制】表名、列名禁止使用关键字
6.【强制】创建表时必须显示指定表存储引擎类型。无特殊需要,一律为InnoDB。
7.【强制】建表必须有comment。
8.【强制】字段名应尽可能使用表达式及含义的英文单词或缩写。
9.【强制】布尔值类型的字段名为is_描述.
10.【强制】禁止在数据库中存储图片,文件等大的二进制数据,只存储文件地址
11.【建议】建表时必须有主键。
12.【建议】核心表必须有行数据的创建时间字段和最后更新字段,便于查找问题。
13.【建议】表中所有字段尽量都是not null属性,业务可以根据需要自定义default值。
14.【建议】所有存储相同数据的列名和列类型必须一直
15.【建议】中间表用户保留中间结果集,名称以tmp_开头
备份库以bak_为前缀,并以日期为后缀;
10.3 关于索引
1.【强制】InnoDB表必须主键为id int/bigint auto_increment,且主键值禁止被更新。
2.【强制】InnoDB和MyISAM存储引擎表,索引类型必须为BTREE。
3.【建议】逐渐的名称以pk_开头,唯一键以uni_或uk_开头,普通索引以 idx_ 开头,一律使用小写格式,一字段的名称或缩写作为后缀。
4.【建议】多单词组成的columnname,取前几个单词首字母,加末单词组成column_name。
5.【建议】单个表上的索引个数 不能超过6个。
6.【建议】在建立索引时,多考虑建立联合索引,并把区分度最高的字段放在最前面
7.【建议】在多表join的sql里,保证被驱动表的连接列上由索引,这样join执行效率最高。
8.【建议】建表或加索引时,保证表里互相不存在 冗余索引。
10.4 sql编写
1.【强制】select语句必须执行具体字段名,禁止 *
2.【建议】程序端insert语句指定具体字段名称,不要写成insert into t1 value()。
3.【建议】除静态表或小表,DML语句必须由where条件,且使用索引查找。
4.【建议】insert into 。。。values(),(),()....这里的之不要超过5000个。值过多虽然上线很快,但会引起主从同步延时
5.【建议】select 语句不要使用union,推荐使用union all,并且union子句个数限制在5个以内。
6.【建议】减少使用order by,和业务沟通能不排序就不排序,获奖排序放到程序段做。order by,group by, distinct 这些语句较为耗费cpu,数据库的cpu资源是极其宝贵的。
7.【建议】线上环境,多表join不要超过5个
8.【建议】包含了order by,group by,distinct 这些查询的语句,where 条件过滤出来的结果集请保持在1000以内,否则sql会很慢
9.【建议】对单表的多次alter操作必须合并为一次。
10.【建议】批量操作数据时,需要控制事务处理间隔时间,进行必要的sleep
11.【建议】事务里包含sql不超过5个
12.【建议】事务里更新语句尽量基于主键或unique key,如update。。。where id =xx;