Oracle优化器在任何可能的时候都会对表达式进行评估并且把特定的语法结构转换成等价的结构这么做的原因是
·要么结果表达式能够比源表达式具有更快的速度
·要么源表达式只是结果表达式的一个等价语义结构
不同的SQL结构有时具有同样的操作(例如= ANY (subquery) and IN (subquery))Oracle会把他们映射到一个单一的语义结构
下面将讨论优化器如何评估优化如下的情况和表达式
常量 LIKE 操作符 IN 操作符 ANY和SOME 操作符 ALL 操作符 BETWEEN 操作符 NOT 操作符
传递(Transitivity) 确定性(DETERMINISTIC)函数
常量
常量的计算是在语句被优化时一次性完成而不是在每次执行时下面是检索月薪大于的的表达式 · sal > /
· sal >
· sal* >
如果SQL语句包括第一种情况优化器会简单地把它转变成第二种
注意优化器不会简化跨越比较符的表达式例如第三条语句鑒于此应用程序开发者应该尽量写用常量跟字段比较检索的表达式而不要将字段置于表达式当中
LIKE 操作符
优化器把使用LIKE操作符和一个没有通配符的表达式组成的检索表达式转换为一个“=”操作符表达式
例如优化器会把表达式ename LIKE SMITH转换为ename = SMITH优化器只能转换涉及到可变长数据类型的表达式前一个例子中如果ENAME字段的类型是CHAR() 那么优化器将不做任何转换
IN 操作符
优化器把使用IN比较符的检索表达式替换为等价的使用“=”和“OR”操作符的检索表达式例如优化器会把表达式ename IN (SMITHKINGJONES)替换为: ename = SMITH OR ename = KING OR ename = JONES
ANY和SOME 操作符
优化器将跟随(following)值列表的ANY和SOME检索条件用等价的同等操作符和“OR”组成的表达式替换
例如优化器将如下所示的第一条语句用第二条语句替换 · sal > ANY (:first_sal :second_sal)
· sal > :first_sal OR sal > :second_sal
优化器将跟随子查询的ANY和SOME检索条件转换成由“EXISTS”和一个相应的子查询组成的检索表达式
例如优化器将如下所示的第一条语句用第二条语句替换 · x > ANY (SELECT sal FROM emp WHERE job = ANALYST)
· EXISTS (SELECT sal FROM emp WHERE job = ANALYST AND x > sal)
ALL 操作符
优化器将跟随值列表的ALL操作符用等价的“=”和“AND”组成的表达式替换
例如sal > ALL (:first_sal :second_sal)表达式会被替换为 sal > :first_sal AND sal > :second_sal
对于跟随子查询的ALL表达式优化器用ANY和另外一个合适的比较符组成的表达式替换例如优化器会把表达式 x > ALL (SELECT sal FROM emp WHERE deptno = ) 替换为 NOT (x <= ANY (SELECT sal FROM emp WHERE deptno = ))
接下来优化器会把第二个表达式适用ANY表达式的转换规则转换为下面的表达式 NOT EXISTS (SELECT sal FROM emp WHERE deptno = AND x <= sal)
BETWEEN 操作符
优化器总是用“>=”和“<=”比较符来等价的代替BETWEEN操作符例如优化器会把表达式sal BETWEEN AND 用sal >= AND sal <= 来代替
NOT 操作符
优化器总是试图简化检索条件以消除“NOT”逻辑操作符的影响这将涉及到“NOT”操作符的消除以及代以相应的比较运算符
例如优化器将下面的第一条语句用第二条语句代替 · NOT deptno = (SELECT deptno FROM emp WHERE ename = TAYLOR)
· deptno <> (SELECT deptno FROM emp WHERE ename = TAYLOR)
通常情况下一个含有NOT操作符的语句有很多不同的写法优化器的转换原则是使“NOT”操作符后边的子句尽可能的简单即使可能会使结果表达式包含了更多的“NOT”操作符例如优化器将如下所示的第一条语句用第二条语句代替 · NOT (sal < OR comm IS NULL)
· NOT sal < AND comm IS NOT NULL sal >= AND comm IS NOT NULL
传递(Transitivity)
如果“WHERE”子句的两个检索条件涉及了一个共同的字段优化器有时会根据传递原理推断出第三个检索条件随后可以根据这个推断出的条件对语句 进行优化推断出的条件可能会激活一个原来的检索条件没有激活的潜在的接口路径(access path)注意传递仅仅被用在基于代价(costbased)的优化中
假设有一个这样的包含两个检索条件的“WHERE”子句WHERE 字段 常量 AND字段 = 字段在这个例子里优化器会推断出新的检索条件字段 常量在这里是比较运算符=!=^=<>><= 或 >=之中的任何一个常量是指任何一个涉及了操作符SQL函数文字绑定变量(bind variables)或者关联变量(correlation variables)的常量表达式
例如考虑这样一个包含两个各自使用了字段EMPDEPTNO的检索条件的WHERE子句的查询 SELECT * FROM emp dept WHERE empdeptno = AND empdeptno = deptdeptno;
使用传递优化优化器会推断出如下条件deptdeptno = 如果有索引存在于EMPDEPTNO字段上这个条件会使调用这个索引的接口路径有效注意优化器只能对字段关联常量的表达式进行推断而不是 字段关联字段的表达式例如包含这样条件的WHERE子句字段 字段 AND 字段 = 字段这种情况不能推断出表达式字段 < comp_oper> 字段
确定性(DETERMINISTIC)函数
在某些情况下优化器能够使用先前的函数返回结果而不是重新执行用户定义的函数这仅仅对那些以限制的方式来执行的函数来说是有效的这些函数必须 对任何的输入都有同样的返回值函数的结果必须不能因为包(PACKAGE)变量数据库或会话(SESSION)的参数(例如NLS参数)不同而变化 如果函数在将来重新定义返回值必须对任何参数来说仍然与以前的返回值相同函数的创建者可以在以CREATE FUNCTIONCREATE PACKAGE或者CREATE TYPE声明函数时根据以上的要求使用DETERMINISTIC关键字向数据库申明该函数为确定性函数数据库不会对确定性函数的合法性进行校验即使 一个函数明显的使用了包变量或操作了数据库仍然可以被定义为确定性函数这就是说如何安全合法的使用和定义确定性函数是程序员的责任
当确定性函数在同一个查询里被多次调用或者被基于函数的索引或物化视图(materialized view)调用时有可能被一个已经计算出的值取代