1. 程式人生 > >資料庫SQL優化

資料庫SQL優化

SQL優化   我們要做到不但會寫 SQL,還要做到寫出效能優良的 SQL。SQL優化需要注意及遵循的準則很多,本文只列舉核心部分: 

1) 儘量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替。  

2) 不用NOT IN操作符,可以用NOT EXISTS或者外連線+(外連線+判斷為空)

替代。  3) 不用“<>”或者“!=”操作符。對不等於操作符的處理會造成全表掃描,可 以用“<” or “>”代替。例如:a<>0 改為 a>0 or a<0,a<>’ ’ 改為 a>’ ’ 

 4) Where子句中出現IS NULL或者IS NOT NULL時,Oracle會停止使用索引而執

行全表掃描。可以考慮在設計表時,對索引列設定為NOT NULL。這樣就可以用其他操作來取代判斷NULL的操作。   5) 當萬用字元“%”或者“_”作為查詢字串的第一個字元時,索引不會被使用, 因此一般不要作為第一個字元出現。   6) 對於有連線的列“||”,最後一個連線列索引會無效。儘量避免連線,可以 分開連線或者使用不作用在列上的函式替代。   7) 如果索引不是基於函式的,那麼當在Where子句中對索引列使用函式時,索 引不再起作用。   8) Where子句中避免在索引列上使用計算,否則將導致索引失效而進行全表掃 描。   9) 對資料型別不同的列進行比較時,會使索引失效。   10) 用“>=”替代“>”。   11) UNION操作符會對結果進行篩選,消除重複,資料量大的情況下可能會引起 磁碟排序。如果不需要刪除重複記錄,應該使用UNION ALL。

  12) Oracle從下到上處理Where子句中多個查詢條件,所以表連線語句應寫在其 他Where條件前,可以過濾掉最大數量記錄的條件必須寫在Where子句的末尾。   13) Oracle從右到左處理From子句中的表名,所以在From子句中包含多個表的 情況下,將記錄最少的表放在最後。   14) Order By語句中的非索引列會降低效能,可以通過新增索引的方式處理。嚴 格控制在Order By語句中使用表示式。   15) 不同區域出現的相同的Sql語句,要保證查詢字元完全相同,以利用SGA共 享池,防止相同的Sql語句被多次分析。  16) 多利用內部函式提高Sql效率。   17) 當在Sql語句中連線多個表時,使用表的別名,並將之作為每列的字首。這 樣可以減少解析時間。   18) 根據SQL不同設定優化模式的方式,選擇不同的優化策略,通過SELECT  /*+ALL+_ROWS*/ „„;來設定。可用的HINT包括/*+ALL_ROWS*/、/*+FIRST_ROWS*/、/*+CHOOSE*/、/*+RULE*/ 等一般在SQL前加first_rows策略,速度都會提高,特殊情況下改用choose策略。   19) 對於大表查詢中的列應儘量避免進行諸如To_char,to_date, to_number等轉換。   20) 有索引的儘量用索引,有用到索引的條件寫在前面 。  21) 如有可能和有必要就建立一些索引 ,在使用索引欄位作為條件時,如果該 索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。  22) 儘量避免進行全表掃描,限制條件儘可能多,以便更快搜索到要查詢的資料。

23) Select子句中儘量避免使用‘*’,當你想在SELECT子句中列出所有的COLUMN 時,使用動態SQL列引用 ‘*’ 是一個方便的方法。但是,這是一個非常低效的方法。實際上,ORACLE在解析的過程中,會將‘*’ 依次轉換成所有的列名,這個工作是通過查詢資料字典完成的,這意味著將耗費更多的時間。合理寫WHERE子句,不要寫沒有WHERE的SQL語句。 

  24) 減少訪問資料的次數,當執行每條SQL語句時, 資料庫在內部執行了許多 工作: 解析SQL語句, 估算索引的利用率, 繫結變數 , 讀資料塊等等。 由此可見, 減少訪問資料庫的次數 , 就能實際上減少資料庫的工作量。  25) 查詢的模糊匹配,儘量避免在一個複雜查詢裡面使用 LIKE '%parm1%'——百 分號會導致相關列的索引無法使用,最好不要用。解決辦法:其實只需要對該指令碼略做改進,查詢速度便會提高近百倍。改進方法如下:  a、修改前臺程式——把查詢條件的供應商名稱一欄由原來的文字輸入改為下拉列表,使用者模糊輸入供應商名稱時,直接在前臺就幫忙定位到具體的供應商,這樣在呼叫後臺程式時,這列就可以直接用等於來關聯了。  b、直接修改後臺——根據輸入條件,先查出符合條件的供應商,並把相關記錄儲存在一個臨時表裡頭,然後再用臨時表去做複雜關聯。  儘量避免在索引過的字元資料中,使用非打頭字母搜尋。這也使得引擎無法利用索引。 見如下例子:   SELECT * FROM T1 WHERE NAME LIKE ‘%L%’  SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’  SELECT * FROM T1 WHERE NAME LIKE ‘L%’   即使NAME欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有資料逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。  26) 避免使用耗費資源的操作,帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY 的SQL語句會啟動SQL引擎 執行,耗費資源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排序。  27) 儘量減少重複工作,控制同一條語句的多次執行,減少多次的資料轉換,減 少不必要的子查詢和連線表,合併對同一張表的多次update操作,update操作不要拆成delete+insert操作,雖然功能相同,但效能差別很大。  28) 多表連線的連線條件對索引選擇有重要意義,在寫連線條件時要特別注意。 多表連線時,連線條件必須寫全,儘量使用聚集索引。  充分利用連線條件,在某種情況下,兩個表之間可能不只一個的連線條件,這時在 WHERE 子句中將連線條件完整的寫上,有可能大大提高查詢速度。  

  29) 避免使用不相容的資料型別。例如float和int、char和varchar、binary和 varbinary是不相容的。資料型別的不相容可能使優化器無法執行一些本來可以進行的優化操作。例如:   SELECT name FROM employee WHERE salary > 60000   在這條語句中,如salary欄位是money型的,則優化器很難對其進行優化,因為60000是個整型數。我們應當在程式設計時將整型轉化成為錢幣型,而不要等到執行時轉化。  30) 儘量不要用SELECT INTO語句。   SELECT INTO 語句會導致表鎖定,阻止其他使用者訪問該表。  31) 使用檢視加速查詢。  把表的一個子集進行排序並建立檢視,有時能加速查詢。它有助於避免多重排序操作,而且在其他方面還能簡化優化器的工作。檢視中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁碟I/O,所以查詢工作量可以得到大幅減少。 ---------------------  作者:辛修燦  來源:CSDN  原文:https://blog.csdn.net/u012743772/article/details/51135529  版權宣告:本文為博主原創文章,轉載請附上博文連結!