SQL性能優化


1.查詢的模糊匹配

盡量避免在一個復雜查詢里面使用 LIKE '%parm1%'—— 紅色標識位置的百分號會導致查詢走全表掃描,相關列的索引無法使用,除非必要,否則不要在關鍵詞前加%.

解決辦法:

其實只需要對該腳本略做改進,查詢速度便會提高近百倍。改進方法如下:

a、修改前台程序——把查詢條件的供應商名稱一欄由原來的文本輸入改為下拉列表, 用戶模糊輸入供應商名稱時,直接在前台就幫忙定位到具體的供應商,這樣在調用后台程 序時,這列就可以直接用等於來關聯了。

b、直接修改后台——根據輸入條件,先查出符合條件的供應商,並把相關記錄保存在 一個臨時表里頭,然后再用臨時表去做復雜關聯

2.索引問題

在做性能跟蹤分析過程中,經常發現有不少后台程序的性能問題是因為缺少合適索引 造成的,有些表甚至一個索引都沒有。這種情況往往都是因為在設計表時,沒去定義索 引,而開發初期,由於表記錄很少,索引創建與否,可能對性能沒啥影響,開發人員因此 也未多加重視。然一旦程序發布到生產環境,隨着時間的推移,表記錄越來越多

這時缺少索引,對性能的影響便會越來越大了。

這個問題需要數據庫設計人員和開發人員共同關注

法則:不要在建立的索引的數據列上進行下列操作:

◆避免對索引字段進行計算操作

◆避免在索引字段上使用 not,<>,!=

◆避免在索引列上使用 IS NULL 和 IS NOT NULL

◆避免在索引列上出現數據類型轉換

◆避免在索引字段上使用函數

◆避免建立索引的列中使用空值。

3.復雜操作

部分 UPDATE、SELECT 語句 寫得很復雜(經常嵌套多級子查詢)——可以考慮適當拆 成幾步,先生成一些臨時數據表,再進行關聯操作

4.update

同一個表的修改在一個過程里出現好幾十次,如:

update table1
set col1=...
where col2=...;
update table1
set col1=...
where col2=...
......

像這類腳本其實可以很簡單就整合在一個 UPDATE 語句來完成(前些時候在協助 xxx 項 目做性能問題分析時就發現存在這種情況)

5.在可以使用 UNION ALL 的語句里,使用了 UNION

UNION 因為會將各查詢子集的記錄做比較,故比起 UNION ALL ,通常速度都會慢上許 多。一般來說,如果使用 UNION ALL 能滿足要求的話,務必使用 UNION ALL。還有一種情 況大家可能會忽略掉,就是雖然要求幾個子集的並集需要過濾掉重復記錄,但由於腳本的 特殊性,不可能存在重復記錄,這時便應該使用 UNION ALL,如 xx 模塊的某個查詢程序就 曾經存在這種情況,見,由於語句的特殊性,在這個腳本中幾個子集的記錄絕對不可能重 復,故可以改用 UNION ALL)

6.在 WHERE 語句中,盡量避免對索引字段進行計算操作

這個常識相信絕大部分開發人員都應該知道,但仍有不少人這么使用,我想其中一個 最主要的原因可能是為了編寫寫簡單而損害了性能,那就不可取了

9 月份在對 XX 系統做性能分析時發現,有大量的后台程序存在類似用法,如:

......
where trunc(create_date)=trunc(:date1)

雖然已對 create_date 字段建了索引,但由於加了 TRUNC,使得索引無法用上。此處 正確的寫法應該是

where create_date>=trunc(:date1) and
create_date<trunc(:date1)+1< pre=""></trunc(:date1)+1<>

或者是

where create_date between trunc(:date1) and
trunc(:date1)+1-1/(24*60*60)

注意:因 between 的范圍是個閉區間(greater than or equal to low value and less than or equal to high value.), 故嚴格意義上應該再減去一個趨於 0 的小數,這里暫且設置成減去 1 秒 (1/(24*60*60)),如果不要求這么精確的話,可以略掉這步。

7.對 Where 語句的法則

7.1 避免在 WHERE 子句中使用 in,not in,or 或者 having。

可以使用 exist 和 not exist 代替 in 和 not in。

可以使用表鏈接代替 exist。Having 可以用 where 代替,如果無法代替可以分兩步處 理。

例子:

SELECT * FROM ORDERS WHERE CUSTOMER_NAME NOT IN
(SELECT CUSTOMER_NAME FROM CUSTOMER)

優化:

SELECT * FROM ORDERS WHERE CUSTOMER_NAME not exist
(SELECT CUSTOMER_NAME FROM CUSTOMER)

7.2 不要以字符格式聲明數字,要以數字格式聲明字符值。(日期同樣)否則會使索 引無效,產生全表掃描。

例子使用:

SELECT emp.ename, emp.job FROM emp WHERE emp.empno =
7369;
不要使用:SELECT emp.ename, emp.job FROM emp WHERE
emp.empno =7369

8.對 Select 語句的法則

在應用程序、包和過程中限制使用 select * from table 這種方式。看下面例子

使用: SELECT empno,ename,category FROM emp WHERE empno = '7369‘ 

而不要使用: SELECT * FROM emp WHERE empno = '7369' 

9. 排序

避免使用耗費資源的操作,帶有 DISTINCT,UNION,MINUS,INTERSECT,ORDER BY 的 SQL 語句會啟動 SQL 引擎 執行,耗費資源的排序(SORT)功能. DISTINCT 需要一次排序操作, 而其他的至少需要執行兩次排序

10.臨時表

慎重使用臨時表可以極大的提高系統性能


免責聲明!

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



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