产品目录
序言强化前科学知识预备MySQL表亲密关系表头类别结构设计资料库三本体论手写高效率SQL强化提议序言
后面,我们已经控制系统的自学了SQL此基础。第一集该文,已经开始步入SQL强化部份。强化主要就分成三大各方面,依次是句子强化、检索强化、甚感强化。所以。那时主要就要学SQL句子强化。第一集该文适宜下列听众:”理工学院里没自学过SQL或忘了”;”不确切他们建表建的对不对?”;”我写的句子还能强化吗,会不能搞崩伺服器?”:”直面子公司正式宣布资料库,科亮颤抖,深怕两个不当心,删库(* ̄︶ ̄),GG”。以内,也是生前的个人经历,那时将踩过的坑,剖析出,期望也能协助到你。
强化前科学知识预备
1、表间的亲密关系
上一则该文最终,创建表与此同时增设了束缚。那么,束缚除了两个十分关键的促进作用是创建表与表间的联络,透过定义方法关连,最终逐步形成完备的销售业务资料库。
①两对多
两对多是两个虚拟的某一统计数据与除此之外两个虚拟的数个统计数据有关连亲密关系, 比如说: 使用者表和使用者订货表。两个用户有数个订货。
②两对一
比如说: 雇员表和雇员职务表。两个使用者相关联两个职务中文名称。
③多对多
比如说: 小学生表和教员表、小学生教员亲密关系表。两个小学生能有数个教员,两个教员也能有数个小学生。
2、表头类别结构设计
① 表头类型优先选择符合存储需要的最小类别
表头类别优先级:int>date;time >enum>char;varchar>blob
原因:整型,time运算快,节省内存;enum列内部是用整型存储的,char,varchar要考虑字符集的转换和排序的校对集,速度慢;blob无法使用临时表。
② 够用就行(如smallint,varchar(N))
原因:大的表头浪费内存,影响速度,如varchar(10),varchar(300),虽然存储的内容一样,但是,在表联查时,varchar(300)要花更多内存。
③ 尽量避免使用允许为null()
原因:null不利于检索,要用特殊的字节标注,在磁盘上占的空间其实更大
例子:建两个相同表头的表,两个允许为null,两个不允许。能发现为null的检索更大些。④ 避免使用ENUM类别
修改ENUM值需要使用ALTER句子,ENUM类别的ORDER BY操作效率低,需要额外操作,禁止使用数值作为ENUM的枚举值。
⑤ 使用TIMESTAMP(4个字节)或DATETIME类别(8个字节)存储时间
TIMESTAMP 存储的时间范围 1970-01-01 00:00:01 ~ 2038-01-19-03:14:07
TIMESTAMP 占用4字节和INT相同,但比INT可读性高。
超出TIMESTAMP取值范围的使用DATETIME类别存储。⑥ 金额类统计数据使用decimal
Decimal类别为精准浮点数,在计算时不能丢失精度。
占用空间由定义的宽度决定,每4个字节能存储9位数字,并且小数点要占用两个字节,可用于存储比bigint更大的整型统计数据。
3、资料库的三大本体论
① 字段不可再分
第一本体论的合理遵循需要根据控制系统的实际需求来定。比如说某些资料库控制系统中需要用到“地址”这个属性,本来直接将“地址”属性结构设计成两个资料库表的表头就行。但是如果控制系统经常会访问“地址”属性中的“城市”部份,所以就非要将“地址”这个属性重新拆分成省份、城市、详细地址等数个部份进行存储,这样在对地址中某一部份操作的时候将十分方便。这样结构设计才算满足了资料库的第一本体论,如下表所示:
使用者信息遵循了第一本体论的要求,这样在对使用者使用城市进行分类的时候就十分方便,也提高了资料库的性能。
② 非主属性完全依赖于主键(确保表中的每列都和主键相关)
第二本体论在第一本体论的此基础之上更进一层。两个表只能保存一种统计数据,不能将多种统计数据存在同一张统计数据表里。比如说要结构设计两个订货信息表,因为订货中可能会有多种商品,所以要将订货编号和商品编号作为资料库表的联合主键,如下表所示:这样就产生两个问题:这个表中是以订货编号和商品编号作为联合主键。这样在该表中商品中文名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。
所以在这里违反了第二本体论的结构设计原则。而如果把这个订货信息表进行拆分,把商品信息分离到另两个表中,把订货项目表
③确保每列都和主键直接相关,不能间接相关
比如说在结构设计两个订货统计数据表的时候,能将客户编号作为两个定义方法和订货表创建相应的亲密关系。而不能在订货表中添加关于客户其它信息(比如说姓名、所属子公司等)的表头。如下面这两个表所示的结构设计就是两个满足第三本体论的资料库表。
这样在查询订货信息的时候,就能使用客户编号来引用客户信息表中的记录,也不必在订货信息表中多次输入客户信息的内容,减小了统计数据冗余。
手写高效率SQL强化提议
1、避免使用SELECT * 替换成SELECT <表头列表> 查询
原因:消耗更多的CPU和IO以网络带宽资源;无法使用覆盖检索;可减少表结构变更带来的影响
2、避免使用不含表头列表的INSERT句子
# 如: insert into values (a,b,c); # 应使用: insert into t(c1,c2,c3) values (a,b,c);3、Inner join 、left join、right join,优先使用 Inner join,如果是 left join,左边表结果尽量小
Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集。
left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。
都满足 SQL 需求的前提下,推荐优先使用 Inner join(内连接),如果要使用 left join,左边表统计数据结果尽量小,如果有条件的尽量放到左边处理。
4、避免使用JOIN关连超过5个以内表
对于Mysql来说,是存在关连缓存的,缓存的大小能由join_buffer_size参数进行增设。
原因:在Mysql中,对于同两个SQL多关连(join)两个表,就会多分配两个关连缓存,如果在两个SQL中关连的表越多,所占用的内存也就越大。如果程序中大量的使用了多表关连的操作,与此同时join_buffer_size增设的也不合理的情况下,就容易造成伺服器内存溢出的情况,就会影响到伺服器资料库性能的稳定性。与此同时对于关连操作来说,会产生临时表操作,影响查询效率,Mysql最多允许关连61个表,提议不超过5个。
5、 减少同资料库的交互次数
资料库更适宜处理批量操作,合并数个相同的操作到一起,能提高处理效率。比如说:插入统计数据过多,考虑批量插入。
6、慎用 distinct 关键字
distinct关键字一般用来过滤重复记录,以返回不重复的记录。在查询两个表头或者很少表头的情况下使用时,给查询带来强化效果。但是在表头很多的时候使用,却会大大降低查询效率。
7、禁止使用order by rand() 进行随机排序
原因:order by rand()会把表中所有符合条件的统计数据装载到内存中,然后在内存中对所有统计数据根据随机生成的值进行排序,并且可能会对每一行都生成两个随机值,如果满足条件的统计数据集十分大,就会消耗大量的CPU和IO及内存资源。
8、使用 where 条件限定要查询的统计数据,避免返回多余的行
需要什么统计数据,就去查什么统计数据,避免返回不必要的统计数据,节省开销。
9、在明显不能有重复值时使用UNION ALL 而不是UNION
UNION 会把两个结果集的所有统计数据放到临时表中后再进行去重操作,
UNION ALL 不能再对结果集进行去重操作
10、 拆分复杂的大SQL为多个小SQL
大SQL逻辑上比较复杂,需要占用大量CPU进行计算的SQL
MySQL中,两个SQL只能使用两个CPU进行计算
SQL拆分后能透过并行执行来提高处理效率。
11、where 子句中考虑使用默认值代替 NULL
# 反例 select * from user where age is not null; # 正例 # 增设0为默认值 select * from user where age>0;12、exist&in 的合理利用
MySQL 强化原则,就是小表驱动甚感,小的统计数据集驱动大的统计数据集,从而让性能更优。因此,我们要选择最外层循环小的,也就是,如果 B 的统计数据量小于 A,适宜使用 in,如果 B 的统计数据量大于 A,即适宜选择 exist。