Oracle8i基於規則的最佳化機制對錶達式的處理 (轉)

gugu99發表於2007-10-14
Oracle8i基於規則的最佳化機制對錶達式的處理 (轉)[@more@]  器在任何可能的時候都會對進行評估,並且把特定的語法結構轉換成等價的結構,這麼做的原因是:

·  要麼結果表示式能夠比源表示式具有更快的速度

·  要麼源表示式只是結果表示式的一個等價語義結構

不同的結構有時具有同樣的操作(例如:= ANY (subquery) and IN (subquery)),ORACLE會把他們對映到一個單一的語義結構。

下面將討論最佳化器如何評估最佳化如下的情況和表示式:常量 LIKE 運算子 IN 運算子 ANY和SOME 運算子 ALL 運算子 BETWEEN 運算子 NOT 運算子 傳遞(Transitivity) RmiNISTIC)">確定性(DETERMINISTIC)函式

常量:namespace prefix = o ns = "urn:schemas--com::office" />

常量的計算是在語句被最佳化時一次性完成,而不是在每次時。下面是檢索月薪大於2000的的表示式:

·  sal > 24000/12

·  sal > 2000

·  sal*12 > 24000

如果SQL語句包括第一種情況,最佳化器會簡單地把它轉變成第二種。 

注意:最佳化器不會簡化跨越比較符的表示式,例如第三條語句,鑑於此,應用開發者應該儘量寫用常量跟欄位比較檢索的表示式,而不要將欄位置於表示式當中。

LIKE 運算子

最佳化器把使用LIKE運算子和一個沒有萬用字元的表示式組成的檢索表示式轉換為一個“=”運算子表示式。

例如:最佳化器會把表示式ename LIKE 'SMITH'轉換為ename = 'SMITH'

最佳化器只能轉換涉及到可變長資料型別的表示式,前一個例子中,如果ENAME欄位的型別是CHAR(10), 那麼最佳化器將不做任何轉換。

IN 運算子

最佳化器把使用IN比較符的檢索表示式替換為等價的使用“=”和“OR”運算子的檢索表示式。

例如,最佳化器會把表示式ename IN ('SMITH','KING','JONES')替換為

  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 ( 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 = 10) 替換為:

  NOT (x <= ANY (SELECT sal FROM emp WHERE deptno = 10))

接下來最佳化器會把第二個表示式適用ANY表示式的轉換規則轉換為下面的表示式:

  NOT EXISTS (SELECT sal FROM emp WHERE deptno = 10 AND x <= sal)

BETWEEN 運算子

最佳化器總是用“>=”和“<=”比較符來等價的代替BETWEEN運算子。

例如:最佳化器會把表示式sal BETWEEN 2000 AND 3000用sal >= 2000 AND sal <= 3000來代替。

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 < 1000 OR comm IS NULL)

·  NOT sal < 1000 AND comm IS NOT NULL sal >= 1000 AND comm IS NOT NULL

傳遞(Transitivity)

如果“WHERE”子句的兩個檢索條件涉及了一個共同的欄位,最佳化器有時會根據傳遞原理推斷出第三個檢索條件,隨後可以根據這個推斷出的條件對語句進行最佳化,推斷出的條件可能會啟用一個原來的檢索條件沒有啟用的潛在的介面路徑(access path)。

注意傳遞僅僅被用在基於代價(cost-based)的最佳化中。

假設有一個這樣的包含兩個檢索條件的“WHERE”子句:WHERE 欄位1 常量 AND欄位1 = 欄位2,在這個例子裡,最佳化器會推斷出新的檢索條件:欄位2 常量。在這裡,是比較運算子=、!=、^=、<>、>、<= 或 >=之中的任何一個,常量是指任何一個涉及了運算子、SQL函式、文字、繫結變數(bind variables)或者關聯變數(correlation variables)的常量表示式。

例如,考慮這樣一個包含兩個各自使用了欄位EMP.DEPTNO的檢索條件的WHERE子句的查詢:

SELECT * FROM emp, dept WHERE emp.deptno = 20 AND emp.deptno = dept.deptno;

使用傳遞最佳化,最佳化器會推斷出如下條件:dept.deptno = 20

如果有存在於EMP.DEPTNO欄位上,這個條件會使這個索引的介面路徑有效。

注意:最佳化器只能對欄位關聯常量的表示式進行推斷,而不是欄位關聯欄位的表示式。例如,包含這樣條件的WHERE子句:欄位1 欄位3 AND 欄位1 = 欄位2,這種情況不能推斷出表示式:欄位2 < comp_oper> 欄位3。

確定性(DETERMINISTIC)函式

在某些情況下,最佳化器能夠使用先前的函式返回結果而不是重新執行定義的函式,這僅僅對那些以限制的方式來執行的函式來說是有效的。這些函式必須對任何的輸入都有同樣的返回值,函式的結果必須不能因為包(PACKAGE)變數、或會話(SESSION)的引數(例如NLS引數)不同而變化,如果函式在將來重新定義,返回值必須對任何引數來說仍然與以前的返回值相同。函式的建立者可以在以CREATE FUNCTION、CREATE PACKAGE或者CREATE TYPE宣告函式時根據以上的要求使用DETERMINISTIC關鍵字向資料庫申明該函式為確定性函式,資料庫不會對確定性函式的合法性進行校驗,即使一個函式明顯的使用了包變數或操作了資料庫,仍然可以被定義為確定性函式,這就是說如何合法的使用和定義確定性函式是程式設計師的責任。

當確定性函式在同一個查詢裡被多次呼叫,或者被基於函式的索引或物化檢視(materialized view)呼叫時,有可能被一個已經計算出的值取代


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-976376/,如需轉載,請註明出處,否則將追究法律責任。

相關文章