優化 : Oracle數據庫Where條件執行順序 及Where子句的條件順序對性能的影響


、Oracle數據庫Where條件執行順序:

由於SQL優化起來比較復雜,並且還會受環境限制,在開發過程中,寫SQL必須必須要遵循以下幾點的原則:

  1.ORACLE采用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾.

  例如:

  (低效)

  SELECT … FROM EMP E WHERE SAL > 50000 AND JOB = ‘MANAGER’ AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO);

  (高效)

  SELECT … FROM EMP E WHERE 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO) AND SAL > 50000 AND JOB = ‘MANAGER’;

  2.SELECT子句中避免使用’*’

  當在SELECT子句中列出所有的COLUMN時,使用動態SQL列引用 ‘*’ 是一個方便的方法.可是,這是一個非常低效的方法. 實際上,ORACLE在解析的過程中, 會將’*’ 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的, 這意味着將耗費更多的時間.

  3.使用表的別名(Alias)

  當在SQL語句中連接多個表時, 請使用表的別名並把別名前綴於每個Column上.這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤.

  注:Column歧義指的是由於SQL中不同的表具有相同的Column名,當SQL語句中出現這個Column時,SQL解析器無法判斷這個Column的歸屬。

 

2、oracle中Where子句的條件順序對性能的影響:

    經常有人問到oracle中的Where子句的條件書寫順序是否對SQL性能有影響,我的直覺是沒有影響,因為如果這個順序有影響,Oracle應 該早就能夠做到自動優化,但一直沒有關於這方面的確鑿證據。在網上查到的文章,一般認為在RBO優化器模式下無影響(10G開始,缺省為RBO優化器模 式),而在CBO優化器模式下有影響,主要有兩種觀點:

  a.能使結果最少的條件放在最右邊,SQL執行是按從右到左進行結果集的篩選的;

  b.有人試驗表明,能使結果最少的條件放在最左邊,SQL性能更高。

  查過oracle8到11G的在線文檔,關於SQL優化相關章節,沒有任何文檔說過where子句中的條件對SQL性能有影響,到底哪種觀點是 對的,沒有一種確切的結論,只好自己來做實驗證明。結果表明,SQL條件的執行是從右到左的,但條件的順序對SQL性能沒有影響。

  實驗一:證明了SQL的語法分析是從右到左的

  下面的試驗在9i和10G都可以得到相同的結果: 第1條語句執行不會出錯,第2條語句會提示除數不能為零。

  1.Select 'ok' From Dual Where 1 / 0 = 1 And 1 = 2;

  2.Select 'ok' From Dual Where 1 = 2 And 1 / 0 = 1;

  證明了SQL的語法分析是從右到左的。

  實驗二:證明了SQL條件的執行是從右到左的

 


  drop table temp; 
  create table temp( t1 varchar2(10),t2 varchar2(10)); 
  insert into temp values('zm','abcde'); 
  insert into temp values('sz','1'); 
  insert into temp values('sz','2'); 
  commit;

  1. select * from temp where to_number(t2)>1 and t1='sz';

  2. select * from temp where t1='sz' and to_number(t2)>1;

  在9i上執行, 第1條語句執行不會出錯,第2條語句會提示“無效的數字”

  在10G上執行,兩條語句都不會出錯。

  說明:9i上,SQL條件的執行確實是從右到左的,但是10G做了什么調整呢?

  實驗三:證明了在10g上SQL條件的執行是從右到左的

Create Or Replace Function F1(v_In Varchar2) Return Varchar2 Is 
  Begin 
  Dbms_Output.Put_Line('exec F1'); 
  Return v_In; 
  End F1; 
  / 
  Create Or Replace Function F2(v_In Varchar2) Return Varchar2 Is 
  Begin 
  Dbms_Output.Put_Line('exec F2'); 
  Return v_In; 
  End F2; 
  / 
  SQL> set serverout on; 
  SQL> select 1 from dual where f1('1')='1' and f2('1')='1'; 
  1 
  ---------- 
  1 
  exec F2 
  exec F1 
  SQL> select 1 from dual where f2('1')='1' and f1('1')='1'; 
  1 
  ---------- 
  1 
  exec F1 
  exec F2

  結果表明,SQL條件的執行順序是從右到左的。

  那么,根據這個結果來分析,把能使結果最少的條件放在最右邊,是否會減少其它條件執行時所用的記錄數量,從而提高性能呢?

  例如:下面的SQL條件,是否應該調整SQL條件的順序呢?

  Where A.結帳id Is Not Null

  And A.記錄狀態<>0

  And A.記帳費用=1

  And (Nvl(A.實收金額, 0)<>Nvl(A.結帳金額, 0) Or Nvl(A.結帳金額, 0)=0)

  And A.病人ID=[1] And Instr([2],','||Nvl(A.主頁ID,0)||',')>0

  And A.登記時間Between [3] And [4]

  And A.門診標志<>1

  實際上,從這條SQL語句的執行計划來分析,Oracle首先會找出條件中使用索引或表間連接的條件,以此來過濾數據集,然后對這些結果數據塊所涉及的記錄逐一檢查是否符合所有條件,所以條件順序對性能幾乎沒有影響。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM