1.1.1.	编写SQL规则
1.1.1.1.	避免使用IN语句
原因
1.	IN用作子查询时,会使查询时间变长,查询效率大大降低
2.	IN会使系统无法使用索引,而只能全表扫描
替代方案
1.	做子查询时,使用EXISTS代替。
例如:SELECT CREATEOR_ID FROM LS_PLAN WHERE PLAN_ID IN(SELECT PLAN_ID FROM LS_TASK)改为:SELECT CREATEOR_ID FROM LS_PLAN WHERE EXISTS (SELECT PLAN_ID FROM LS_TASK WHERE PLAN_ID=LS_PLAN.PLAN_ID)。
2.	查询连续数值,BETWEEN不用IN。
例如:SELECT TASK_ID FROM LS_TASK  WHERE TASK_ID IN(01,02,03) 改为: SELECT TASK_ID FROM LS_TASK  WHERE TASK_ID BETWEEN 01 AND 03。
1.1.1.2.	避免使用DISTINCT
原因
   DISTINCT排序时要排序整张表,效率非常低。
替代方案
   GROUP BY 代替。
   例如:SELECT DISTINCT TASK_ID FROM LS_TASK   改为:
SELECT TASK_ID FROM LS_TASK GROUP BY TASK_ID
1.1.1.3.	合理使用NOT IN和NOT EXISTS
优化说明
1.	子查询结果集较小时(个数或者百数之内),使用NOT IN会优于NOT EXISTS。
2.	子查询具有一定复杂度时(即SQL关联关系较多,例如子查询中包含多个表查询),使用NOT IN会优于NOT EXISTS。
3.	其他情况下NOT EXISTS优于NOT IN。
原因
	NOT EXISTS在总体上要优于NOT IN ,但不是绝对,合理使用NOT IN和NOT EXISTS能有效的减少查询时间。
替代方案
   下面是两种使用NOT IN 的情况:
1.	子查询结果集较小。
例如:SELECT A1_ID FROM A1 WHERE NOT EXISTS (SELECT A1_ID FROM A2 WHERE A1_ID=A1.A1_ID AND A2.A2_ID <100 )
改为: SELECT A1_ID FROM A1 WHERE A1_ID NOT IN (SELECT A2.A1_ID FROM A2 WHERE A2.A2_ID <100)。
2.	子查询有一定复杂度。
例如:SELECT A1_ID FROM A1 WHERE NOT EXISTS (SELECT A1_ID FROM A2 WHERE A1_ID=A1.A1_ID AND A2.A2_ID IN(SELECT A2_ID FROM A3 WHERE A2_ID<100) )
改为: SELECT A1_ID FROM A1 WHERE A1_ID NOT IN (SELECT A1_ID FROM A2 WHERE EXISTS (SELECT A2_ID FROM A3 WHERE A2.A2_ID=A3.A2_ID AND A2_ID<100))。
1.1.1.4.	避免在WHERE子句中对字段进行NULL值判断
原因
WHERE子句进行NULL值判断,容易使导致引擎进行全表扫描。
替代方案
使用空字符串来代替。包括在设计时,尽量不使用空字段,所有的空值都用空字符串表示。
例如:SELECT ID FROM T1 WHERE NUM IS NULL  改为: SELECT ID FROM T1 WHERE NUM = ‘’。
1.1.1.5.	正确使用LIKE
优化说明
1.	当查询的字符串在字段的开头(例如:AB  A在字段开头)时,开头不要放通配符%。
2.	当在函数或者是存储过程中,去搜索某个字段是否拥有某个字符串在里面,不用LIKE。
原因
1.	% 放在开头将无法使用索引而扫描全表
2.	LIKE的使用是有限制的,它不允许跟在它后面的是一个变量或者是字段
替代方案
1.	例如BC在字段开头: SELECT PLAN_ID FROM LS_PLAN WHERE ORGAN_ID LIKE'%BC%' 改为: SELECT PLAN_ID FROM LS_PLAN WHERE ORGAN_ID LIKE'BC%'
2.	用locate 代替。用法:locate(arg1,arg2,<pos>):在arg2中查找arg1第一次出现的位置,指定pos,则从arg2的pos处开始找arg1第一次出现的位置(第三个参数可省略)。
例如:SELECT PLAN_ID FROM LS_PLAN WHERE ORGAN_ID LIKE'%BC%'  改为:SELECT PLAN_ID FROM LS_PLAN WHERE  LOCATE('BC',ORGAN_ID)>0。
1.1.1.6.	避免在 WHERE子句中使用 OR 来连接条件
原因
   若用OR连接的字段中有使用索引的字段,则使用OR 时,就无法利用索引扫描,而会遍历所有记录或所有的索引。
替代方案
   用UNION合并代替OR。
   例如:SELECT A2_NAME FROM A2 WHERE A2_ID =2 OR A2_ID =7;  若A2_ID列存在索引,则改为:SELECT A2_NAME FROM A2 WHERE A2_ID =2 UNION SELECT A2_NAME FROM A2 WHERE A2_ID =7。
1.1.1.7.	避免在WHERE子句的‘=’或者‘<>’的左边对字段进行函数、  算术运算或其他表达式操作
原因
   做此操作可能会使系统无法正确使用索引。
替代方案
   若有运算操作,放在表达式右边。
例如:SELECT A2_ID FROM A3 WHERE A2_ID/2=3 改为  SELECT A2_ID FROM A3 WHERE A2_ID=3*2。
  注:若运算简单,如上例,直接改成SELECT A2_ID FROM A3 WHERE A2_ID=6   效率更高。
1.1.1.8.	避免不必要的排序
原因
   排序是数据库中资源消耗比较大的一种操作,所以在业务允许的情况下,尽量避免不必要的排序。
替代方案
   通过索引来代替排序,在GROUP BY、ORDER BY子句涉及的列上创建索引。(注意索引的排序是升序还是降序)
1.1.1.9.	表连接
原因
   多表连接时,连接的顺序和连接条件影响SQL效率。
替代方案
1.	如果SQL中存在表A、B、C三表连接,则首先应保证最先连接的两表具有较小的子集。
2.	在进行表连接时,为连接字段和查询过滤字段(where 语句后的条件)建立索引,会得到很好的性能提升。
3.	当进行表连接时,确保连接条件只有一个,尤其是大表连接。
1.1.1.10.	使用fetch first N rows only来取多行数据
优化说明
当返回的结果集较多而我们用不到这么多数据时,使用fetch first N rows only。当结果集较多时,返回所有的结果集会增大所需的执行时间。
替代方案
例如,取结果集的前5列: SELECT A2_ID FROM A3 FETCH FIRST 5 ROWS ONLY。
1.1.1.11.	杜绝使用SELECT * FROM…
原因
当返回结果集很多时,会有很高的fetch,占用大量资源。
替代方案
   只取所需要的列,把*改为所需查询的列名。
1.1.1.12.	避免使用CHAR/NCHAR
原因
   定长字段所占存储空间较大
替代方案
   使用VARCHAR/NVARCHAR代替,不仅可以节省空间,而且在一个相对小的字段搜索效率更高。
1.1.1.13.	尽量使用数字型字段
原因
   只含数字信息的字段(例如:电话号码、年龄等)尽量不要使用字符型。若数字信息的字段设计为字符型,会降低查询和连接的性能,并增加存储开销。
替代方案
   使用数字型代替字符型。
1.1.2.	建立索引规则
	索引是表的一个或多个键值的有序列表。如果表上不存在索引,那么必须对SQL查询中引用的每个表进行全面扫描。表中记录数越多,每条记录越长,全表扫描花费的时间越长,因为全表扫描需要顺序访问表中所有的行。虽然对于需要表中大多数记录的复杂查询来说,使用表扫描效率可能更高,但对于只返回表中部分记录的查询,索引扫描可以更有效的访问表中的数据。
1.1.2.1.	根据条件中谓词的选择度创建索引
优化说明
因为建立索引需要占用数据库的存储空间,所以需要在空间和时间性能之间进行权衡。很多时候,只考虑那些条件子句中有条件判断的列上建立索引也有同样的效果,可以节约空间。
优化方法
可以通过简单的select count(*) from tabname where colA=’X’ 这种方式来查看每个谓词条件过滤的总数,过滤出结果集越小,代表选择度越高,如果是建立组合索引,那么应该将该谓词放在首位。
若条件子句中的判断条件为多个,可分别查询每一个判断条件以及组合条件的选择度,若单个条件选择度和整个条件语句差不多时,可直接建立单列索引来节约空间。
例如select count(*) from tabname where colA=’X’ and colB=’Y’
select count(*) from tabname where colA=’X’
select count(*) from tabname where colB=’Y’
	结果分别为:1404、1407、128700
	因为前两条选择度几乎相同,那么只建立对colA建立索引即可。
1.1.2.2.	避免在建有索引的列上使用函数
优化说明
如果在建有索引的列上使用函数,由于函数单调性无法确定,所以函数的返回值和输入值可能无法一一对应,有可能存在索引中位置差别很大的多个列满足带函数的谓词条件,所以DB2优化器无法进行匹配的索引扫描,甚至可能会直接进行全表扫描。
1.1.2.3.	在需要被排序的列上建立索引
使用背景
   一般用于没有条件语句的查询
优化说明
   因为索引本身是有序的,在需要被排序的列上建立索引可以避免查询时再次对数据进行排序,对于没有条件语句的查询,排序会在查询中占有较大比重,因此能利用索引的排序结构进行查询优化。若需要创建联合索引,将需要被排序的列放在联合索引的第一列。这一原则对大表非常有效。
1.1.2.4.	合理使用INCLUDE关键词
使用背景
只能创建在唯一索引中
优化说明
	例如:SELECT NAME FROM ABC WHERE NUM BETWEEN ‘00010’ AND ‘00015’;
在NAME和 NUM上可以建立联合索引来提高查询性能,若NUM是唯一的,就可以使用INCLUDE关键字来创建唯一索引。对于查询来说,INCLUDE的唯一索引和联合索引作用是同等的,但是对于建立索引的时间和以后维护的代价来说,INCLUDE的唯一索引要优于联合索引,它可以有效地减少fetch cost,这对于大表(通常是百万级)来说,十分有效。  
优化方法
	例如:SELECT NAME FROM ABC WHERE NUM BETWEEN ‘00010’ AND ‘00015’;
如此例,NUM是唯一的,可创建唯一索引:
       CREATE UNIQUE INDEX ABC.NUM_1 ON ABC(NUM) INCLUDE (NAME);
1.1.2.5.	指定索引的排序属性
优化说明
   当查询某一列有限定范围时,例如:SELECT MAX(ADD_DATE) FROM TEMP,此时要查询ADD_DATE的最大值时, 索引的降序要比升序的效率更快,所以创建索引时合理的使用ASC和DESC。
1.1.2.6.	索引不是越多越好,合理创建索引
优化说明
   索引会提高相应的SELECT的效率,但同时也会降低UPDATE和INSERT的效率,索引过多会增加SQL语句的编译时间。所以建议,一个表上的索引最好不要超过6个,考虑不常使用的列是否有必要建索引。
1.1.2.7.	尽量不要在主键上创建索引
优化说明
   主键会隐式创建索引,所以不要在主键上创建索引来浪费空间
1.1.2.8.	具有大量重复数据的列上不要创建索引
优化说明
   在大量重复的列上建索引没有任何意义,例如:字段col有大量的重复数据,数据Y占90%,数据N占10%,当查询col=’Y’时,该表的索引扫描和全表扫面没有太大区别,并且建立索引会占用空间。
1.1.2.9.	组合索引
优化说明
1.	考虑到管理上的开销,避免在索引中使用多于5个的列
2.	将查询中使用最多的列放在定义的前边
1.1.3.	拆表规则
1.1.3.1.	水平拆表
使用背景
1.	数据量较大。  
2.	表中的数据有独立性,比如不同地区、不同时间等。  
3.	需要把历史数据和当前数据区分开。
	等以上情况适合水平拆分。
优化说明
   水平拆分是根据某些条件将数据放在两个或多个表中,即按照记录拆分,每个表的表结构完全相同,数据行减少。
优化方法
1.	根据时间日期拆分。例如:某公司一年销售记录较大,可将表按月拆分,每月一张表。
2.	根据地区拆分。例如:某公司各地分公司较多,就可按地区分表。
3.	若根据上述两条拆分,表依旧很大,还可根据其他业务维度分。例如:根据时间地区分表后依旧很大,还可根据产品类型等业务维度再分。
特点
	优点:降低在查询时需要读的数据和索引的页数。降低索引的层数,加快了查询。
	缺点:会给应用增加复杂性,当查询操作时可能需要多个表名,查询所有数据需要UNION操作。对于很多数据库应用,这种复杂性可能会超过它带来的优点。
1.1.3.2.	垂直拆表
使用背景
适用于某些列常用,某些列不常用的表。
优化说明
垂直拆分是根据表的列进行拆分,拆分后的每一张表都带有原表的主键。简单来说就是主键列和一部分列作为一张表,主键列和其他部分列作为另一张表。               
优化方法
1.	把不常用的列放在一张表中。
2.	把经常查询的列放在一张表中。
3.	把text、blob(二进制大对象,是一个可以存储二进制文件的容器)拆分出来放在附表中。
特点
	优点:可使行数据变小,一个数据块可以存放更多数据,减少I/O次数。可以达到最大化利用Cache的目的。
	缺点:垂直拆分后,主键出现冗余,需要管理冗余列。会引起表连接JOIN操作,增加CPU开销,需要从业务上规避。