下面从高效SQL编写的角度谈谈常用的SQL优化方法 1.选择最有效率的表名顺序 大表放在FORM字句的最前面,小表放在FORM字句的最后面。 ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理。在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。当ORACLE处理多个表时,会运用排序及合并的方式连接它们。首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行排序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并。 如果有3个以上的表连接查询, 那就需要选择交叉表(intersECtion table)作为基础表, 交叉表是指那个被其他表所引用的表。
2. WHERE子句中的连接顺序 ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
3. 取别名 在联合表的查询中,表名、列名以一个字母为别名,查询速度要快1.5倍。
4. 字段是否允许为空  NOT NULL字段能用到索引,但允许为NULL的字段,有时却不能。 比如:在表T,字段username建了索引。 select username from t where username='EYGLE' ,能用到索引 select username from t ,不能用到索引  LEFT JOIN 比 INNER JOIN 消耗资源更多 解决方法: 比如,有个学生表,含有民族字段,可不填,不填时存储值为’’(长度为0的字符串)。另外,在民族代码表有条记录为(代码:’’,值:无)。
5. 操作运算符  NOT IN操作符、(不等于) 、!<、!>不能到索引的,因此对它的处理只会产生全表扫描。效率低。 解决办法: not in 可改为表连接或not exists a0 改为 a>0 or a<0 a’’ 改为 a>’’ !< 可改为 >= !> 可改为 运算比>=效率高  <运算比<=效率高
6. 语句效率大比拼  DISTINCT 子句,其效率比GROUP BY 子句高。  WHERE 子句,其效率比HAVING 子句高。  union语句(2至3个)在通常情况下比用or或IN的效率要高  select 字段名 语句比 select * 语句 的效率要高  EXISTS比IN效率高 在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用EXISTS(或NOT EXISTS)通常将提高查询的效率。  EXISTS比DISTINCT效率高 当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT。 一般可以考虑用EXIST替换  表连接比EXISTS效率高 通常来说,采用表连接的方式比EXISTS更有效率
7. 排序 order by后面按索引列排序,比按非索引列或者表达式 排序效率更高
8. 联接列 对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。我们一起来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),现在要查询一个叫比尔.克林顿(Bill Cliton)的职工。   下面是一个采用联接查询的SQL语句,   select * from employss   where   first_name||''||last_name ='Beill Cliton'; 上面这条语句完全可以查询出是否有Bill Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。   当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。   Select * from employee   where first_name ='Beill' and last_name ='Cliton';
9. 预编译SQL 大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。而且大大降低运行时间,当然也加快了访问数据库的速度。 动态SQL,每次执行都需要编译。而且即使在SQL共享池中有一个完全相同的查询值,动态SQL也会重新进行语法分析,而预编译SQL不需要。

« 由 仙外仙 最后编辑于 2011-02-14 23:23:05 。 »