SQL编写规范和优化SQL编写规范--1原则定义1、要求代码行清晰、整齐,具有一定的可观赏性;2、代码编写要充分考虑执行速度最优的原则;3、代码行整体层次分明、结构化强;4、代码中应有必要的注释以增强代码的可读性;5、规范要求非强制性约束代码开发人员的代码编写行为,在实际应用中在不违反常规要求的前提下允许存在可理解的偏差。SQL编写规范--2大小写规则1、所有的SQL语句中的保留字均采用全部大写,不要使用缩写;表别名也要大写;如ALLASCASECREATEDATABASEDELETEFROMININSERTJOINLEFTNONOTNULLOUTSELECTTABLETITLEUPDATEVIEWWHERE等。2、表名、视图名、宏和存储过程名:全部小写;SQL编写规范--2大小写规则3、字段名:每个单词的首字母大写,其余部分小写,如party_id,loc_id,prod_inst_id,Acct_Id,Type_Id等;使用如下语句获得字段列表:SQL编写规范--3缩进和换行整个的SQL语句最好按照子句进行分行编写,SELECT/FROM/WHERE/UPDATE/INSERT等每个关键字都要另起一行。如:SQL编写规范--3缩进和换行SQL编写规范--3缩进和换行1、同一级别的子句间要对齐2、逗号放在每行的开头3、分号放在SQL语句的最后,单独占一行4、每行宽度不超过120字符(每个字符为8个点阵宽),超过行宽的代码可折行与上行对齐编排;5、每个字段后面使用字段标题作为注释6、使用给出的语句获得字段列表和字段标题(借助UltraEdit列模式快速编辑)SQL编写规范--3缩进和换行下面的编写方式不是好的形式:在所有需要缩进的地方,每次缩进4格;在以下情况下需要缩进:1、不同层次的SQL语句之间2、SELECTINSERT等关键字之后的字段列表和关键字之间SQL编写规范--4别名SQL语句别名的命名,分层命名,从第一层次至第四层次,分别用P、S、U、D(都是大写字母)表示,取意为Part,Segment,Unit,Detail。对于同一层次的多个子句,在字母后加1、2、3、4……区分。SQL编写规范--4别名如下图所示:SQL编写规范--5运算符前后间隔要求算术运算符、逻辑运算符的前后至少要保留一个空格,如下图所示:SQL编写规范--6变量引用1、在SQL语句中引用变量时,要在变量名两端加花括号2、对日期变量的引用要在单引号内,如'${MYDATE}'SQL编写规范--7注释针对复杂的SQL语句,请尽量增加相应的注释说明,以便自己和其它同事事后可以比较容易的读懂和修改。注释中应包含以下内容:1、编写人/编写日期2、修改人/修改日期3、该脚本的编写目的与主要内容4、如果有特殊处理、特别的技巧等内容,一定要在注释中详细说明SQL编写规范--7注释5、每一段SQL的前面必须要有注释,重点说明该SQL的技术含义和应用含义、选择理由。技术含义指这段SQL在技术上这么写的原因、好处,应用含义指这段SQL从应用的角度将,是为了达到一个什么样的目的。如果有可能,还需要说明为什么这么选择,而不选择别的方式的理由。如果发现了不足,还可记录不足的原因和建议的解决办法等。SQL编写规范--8连接的使用对于内连接和外连接的使用,要求该使用外连接的地方都已经使用了外连接,不需要外连接的地方一定不使用外连接。表中的字段若是从其它表引用的,要确保该字段在被引用的表中存在。SQL编写规范--8连接的使用要求所有的连接都写成JOIN的形式,如:SQL编写规范--8连接的使用而不要写成:SQL编写规范--8连接的使用另外,为了保证多表连接的连接条件穿透性,要求在多表连接的SQL书写时将连接条件有机的闭环起来,尤其是多表PI相同,并用PI连接时。SQL编写规范--8连接的使用例如:SQL编写规范--8连接的使用即连接条件如下所示:SQL优化(teradata)SQL脚本优化原则要优化脚本,在深刻理解业务逻辑的基础上,一个重要的方式是一段一段的查看SQL的执行计划,然后针对执行计划中不合理、不优化的地方对SQL进行优化编写,这项工作需要实践经验,经常看执行计划会有所帮助。SQL优化(teradata)SQL脚本优化原则表级优化可以参照以下以下优化原则:(1)如果过滤性不很强,又不需要重分布,对大表尽可能不要只做一下过滤就进一次SPOOL,最好是直接与别的表JOIN,边JOIN边过滤了;(2)如果过滤性非常强,可以只做一下过滤就进一次SPOOL;SQL优化(teradata)SQL脚本优化原则(3)SPOOL空间尽量小原则,即尽可能使中间过程中的SPOOL空间小一些,这样可以减小I/O以及继续关联的代价;在此原则下可以引申出下面几个具体原则:(3.1)在几个表大小差不多时,过滤性条件较强的先JOIN;(3.2)在大/大/小三个表内联时,避免先把两个大表JOIN,除非过滤条件非常强;(3.3)在大/小/小三个表内联时,尽量先把两个小表JOIN;(3.4)有时将看似没必要的过滤条件加上,在关联表较多时可能有效的减小SPOOL;如表A、B、C、D的关联字段均为k,即A.k=B.kANDA.k=C.kANDA.k=D.k,而同时还有条件substr(A.k,1,2)='01',有时加上substr(B.k,1,2)='01'、substr(C.k,1,2)='01'、substr(D.k,1,2)='01‘会有好处;SQL优化(teradata)SQL脚本优化原则(4)尽量避免大表重分布;(5)当大表与很小的表(记录数量级在5位数以内)JOIN时,尽量让小表Duplicate;(6)如果必须有重分布时,尽量使之靠后;(7)尽量减少较大的中间过程中的SPOOL空间重分布的次数;SQL优化(teradata)SQL脚本优化原则(8)遇到productjoin时要小心一些;(9)尽量减少对大表的扫描次数;(10)在拆SQL时也应注意,合起来虽然可能大些,但只扫描一次大表,而拆成多句后就要多次扫描大表,可能效率反降;SQL优化(oracle)基于索引的SQL语句优化数据库的优化方法有很多种,在应用层来说,主要是基于索引的优化。难就难在如何判断哪些索引是必要的,哪些又是不必要的。判断的最终标准是看这些索引是否对我们的数据库性能有所帮助。具体到方法上,就必须熟悉数据库应用程序中的所有SQL语句,从中统计出常用的可能对性能有影响的部分SQL,分析、归纳出作为Where条件子句的字段及其组合方式;在这一基础上可以初步判断出哪些表的哪些字段应该建立索引。SQL优化(oracle)基于索引的SQL语句优化其次,必须熟悉应用程序。必须了解哪些表是数据操作频繁的表;哪些表经常与其他表进行连接;哪些表中的数据量可能很大;对于数据量大的表,其中各个字段的数据分布情况如何;等等。对于满足以上条件的这些表,必须重点关注,因为在这些表上的索引,将对SQL语句的性能产生举足轻重的影响SQL优化(oracle)基于索引的SQL语句优化建立索引常用的规则如下:1、表的主键、外键必须有索引;2、数据量超过300的表应该有索引;3、经常与其他表进行连接的表,在连接字段上应该建立索引;4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;5、索引应该建在选择性高的字段上;SQL优化(oracle)基于索引的SQL语句优化6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:A、正确选择复合索引中的主列字段,一般是选择性较好的字段;B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;SQL优化(oracle)基于索引的SQL语句优化C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;SQL优化(oracle)基于索引的SQL语句优化8、频繁进行数据操作的表,不要建立太多的索引;9、删除无用的索引,避免对执行计划造成负面影响;以上是一些普遍的建立索引时的判断依据。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。SQL优化(oracle)基于索引的SQL语句优化太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。SQL优化(oracle)避免对列的操作任何对列的操作都可能导致全表扫描,这里所谓的操作包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等式的右边,甚至去掉函数。例1:下列SQL条件语句中的列都建有恰当的索引,但30万行数据情况下执行速度却非常慢:select*fromrecordwheresubstrb(CardNo,1,4)='5378'(13秒)select*fromrecordwhereamount/301000(11秒)select*fromrecordwhereto_char(ActionTime,'yyyymmdd')='19991201'(10秒)SQL优化(oracle)避免对列的操作由于where子句中对列的任何操作结果都是在SQL运行时逐行计算得到的,因此它不得不进行表扫描,而没有使用该列上面的索引;如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表扫描,因此将SQL重写如下:select*fromrecordwhereCardNolike'5378%'(1秒)select*fromrecordwhereamount1000*30(1秒)select*fromrecordwhereActionTime=to_date('19991201','yyyymmdd')(1秒)差别是很明显的!SQL优化(oracle)避免不必要的类型转换需要注意的是,尽量避免潜在的数据类型转换。如将字符型数据与数值型数据比较,ORACLE会自动将字符型用to_number()函数进行转换,从而导致全表扫描。例2:表tab1中的列col1是字符型(char),则以下语句存在类型转换:selectcol1,col2fromtab1wherecol110,应该写为:selectcol1,col2fromtab1wherecol1'10'。SQL优化(oracle)增加查询的范围限制增加查询的范围限制,避免全范围的搜索。例3:以下查询表record中时间ActionTime小于2001年3月1日的数据:select*fromrecordwhereActionTimeto_date('20010301','yyyymm')查询计划表明,上面的查询对表进行全表扫描,如果我们知道表中的最早的数据为2001年1月1日,那么,可以增加一个最小时间,使查询在一个完整的范围之内。修改如下:SQL优化(oracle)增加查询的范围限制select*fromrecordwhereActionTimeto_date('20010301','yyyymm')andActionTimeto_date('20010101','yyyymm')后一种SQL语句将利用上ActionTime字段上的索引,从而提高查询效率。把'20010301'换成一个变量,根据取值的机率,可以有一半以上的机会提高效率。同理,对于大于某个值的查询,如果知道当前可能的最大值,也可以在Where子句中加上