SQL優化之操作符篇(zt)

tolywang發表於2008-08-13

1.1    IN 操作符     用IN寫出來的SQL的優點是比較輕易寫及清楚易懂,這比較適合現代軟體開發的風格。     但是用IN的SQL效能總是比較低的, 從Oracle執行的步驟來分析用IN的SQL與不用IN的SQL有以下區別:     ORACLE試圖將其轉換成多個表的連線,假如轉換不成功則先執行IN裡面的子查詢,再查詢外層的表記錄,假如轉換成功則直接採用     多個表的連線方式查詢。     由此可見用IN的SQL至少多了一個轉換的過程。一般的SQL都可以轉換成功,但對於含有分組統計等方面的SQL就不能轉換了。     推薦方案:在業務密集的SQL當中儘量不採用IN操作符而使用EXISTS。    

 1.2  NOT IN操作符     此操作是強列推薦不使用的,因為它不能應用表的索引。     推薦方案:用NOT EXISTS代替    

 1.3   <> 操作符(不等於)     不等於操作符是永遠不會用到索引的,因此對它的處理只會產生全表掃描。     推薦方案:用其它相同功能的操作運算代替,如     a<>0 改為 a>0 or a<0
    a<>’’ 改為 a>’’    

1.4 IS NULL 或IS NOT NULL操作(判定欄位是否為空)     判定欄位是否為空一般是不會應用索引的,因為B樹索引是不索引空值的。     推薦方案:     用其它相同功能的操作運算代替,如     a is not null 改為 a>0 或a>’’等。     不答應欄位為空,而用一個預設值代替空值。    

1.5 > 及 < 操作符(大於或小於操作符)     大於或小於操作符一般情況下是不用調整的,因為它有索引就會採用索引查詢,但有的情況下可以對它進行優化,     如一個表有100萬記錄,一個數值型欄位A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。     那麼執行A>2與A>=3的效果就有很大的區別了,因為A>2時ORACLE會先找出為2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄     索引。    

1.6 LIKE操作符     LIKE操作符可以應用萬用字元查詢,裡面的萬用字元組合可能達到幾乎是任意的查詢,但是假如用得不好則會產生效能上的問題,     如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。     一個實際例子:用YW_YHJBQK表中營業編號後面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,     假如改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個範圍的查詢,效能肯定大大提高。    

1.7 UNION操作符     UNION在進行錶連結後會篩選掉重複的記錄,所以在錶連結後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。     select * from gc_dfys
    union
    select * from ls_jg_dfys     這個SQL在執行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,假如表資料量大的話可能會     導致用磁碟進行排序。     推薦方案:     採用UNION ALL操作符替代UNION,因為UNION ALL操作只是簡單的將兩個結果合併後就返回。
    select * from gc_dfys
    union all
    select * from ls_jg_dfys    

1.8 group by用法     Oracle的GROUP BY語句除了最基本的語法外,還支援ROLLUP和CUBE語句。     select topicid,userid,sum(counter) from cis_topic_stat group by rollup(topicid,userid);     也就是說,假如是ROLLUP(A, B, C)的話,首先會對(A、B、C)進行GROUP BY,然後對(A、B)進行GROUP BY,     然後是(A)進行GROUP BY,最後對全表進行GROUP BY操作。     select topicid,userid,sum(counter) from cis_topic_stat group by cube(topicid,userid);     和ROLLUP相比,CUBE又增加了對STATUS列的GROUP BY統計。     假如是GROUP BY CUBE(A, B, C),則首先會對(A、B、C)進行GROUP BY,然後依次是(A、B),(A、C),(A),(B、C),(B),(C),     最後對全表進行GROUP BY操作。    

1.9 如何使用Hint提示     在select/delete/update後寫/*+ hint */     如 select /*+ index(TABLE_NAME INDEX_NAME) */ col1...     注重/*和+之間不能有空格     如用hint指定使用某個索引     select /*+ index(cbotab) */ col1 from cbotab;
    select /*+ index(cbotab cbotab1) */ col1 from cbotab;
    select /*+ index(a cbotab1) */ col1 from cbotab a;     其中     TABLE_NAME是必須要寫的,且假如在查詢中使用了表的別名,在hint也要用表的別名來代替表名;     INDEX_NAME可以不必寫,Oracle會根據統計值選一個索引;     假如索引名或表名寫錯了,那這個hint就會被忽略;

 

 

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

相關文章