數據庫性能優化手法

1.建立必要的索引 (在常常檢索的字段進行建立索引,好比以圖書名稱來進行檢索,就須要在這個圖書名稱的字段建立索引)
2.使用預編譯查詢( 程序中一般是根據用戶的輸入來動態執行 SQL 語句,這時應該儘可能使用參數化 SQL ,這樣不只能夠避免 SQL 注入漏洞攻擊,最重要數據庫會對這些參數化 SQL 執行 預編譯,這樣第一次執行的時候 DBMS 會爲這個 SQL 語句進行查詢優化而且執行預編 譯,這樣之後再執行這個 SQL 的時候就直接使用預編譯的結果,這樣能夠大大提升執 行的速度。)
3.調整 WHERE 子句中的鏈接順序
DBMS 通常採用自下而上的順序解析 WHERE 子句,根據這個原理 , 錶鏈接最好寫
在其餘 WHERE 條件以前,那些能夠過濾掉最大數量記錄。
好比下面的 SQL 語句性能較差:
SELECT *
FROM T_Person
WHERE FSalary > 50000
AND FPosition= ‘MANAGER’
AND 25 < (SELECT COUNT(*) FROM T_Manager
WHERE FManagerId=2);
咱們將子查詢的條件放到最前面,下面的 SQL 語句性能比較好:
SELECT *
FROM T_Person
WHERE
25 < (SELECT COUNT(*) FROM T_Manager
WHERE FManagerId=2)
AND FSalary > 50000
AND FPosition= ‘MANAGER’ ;
4.SELECT語句中避免使用'*'
 
5.儘可能將多條 SQL語句壓縮到一句SQL
6.Where子句替換 HAVING 子句
避免使用 HAVING 子句,由於 HAVING 只會在檢索出全部記錄以後纔對結果集
進行過濾。若是能經過 WHERE 子句限制記錄的數目,那就能減小這方面的開銷。
HAVING 中的條件通常用於聚合函數的過濾,除此而外,應該將條件寫在 WHERE
句中
7. 使用表的別名
當在 SQL 語句中鏈接多個表時,請使用表的別名並把別名前綴於每一個列名上。這
樣就能夠減小解析的時間並減小那些由列名歧義引發的語法錯誤。
8.EXISTS替代 IN
在查詢中,爲了知足一個條件,每每須要對另外一個表進行聯接,在這種狀況下,使
EXISTS 而不是 IN 一般將提升查詢的效率,由於 IN 子句將執行一個子查詢內部的排
序和合並。下面的語句 2 就比語句 1 效率更加高。
語句 1
SELECT * FROM T_Employee
WHERE FNumber> 0
AND FDEPTNO IN (SELECT FNumber
FROM T_Department
WHERE FMangerName = 'Tome')
語句 2SELECT * FROM T_Employee
WHERE FNumber > 0
AND EXISTS (SELECT 1
FROM T_Department
WHERE T_Department. FDEPTNO = EMP.FNumber
AND FMangerName = ‘MELB’ )
9.用錶鏈接替換 EXISTS
一般來講,錶鏈接的方式比 EXISTS 更有效率,所以若是可能的話儘可能使用表連
接替換 EXISTS 。下面的語句 2 就比語句 1 效率更加高。
語句 1
SELECT FName FROM T_Employee
WHERE EXISTS
(
SELECT 1 FROM T_Department
WHERE T_Employee.FDepartNo= FNumber
AND FKind='A'
);
語句 2SELECT FName FROM T_Department, T_Employee
WHERE T_Employee. FDepartNo = T_Departmen. FNumber
AND FKind = ‘A ’ ;
10.避免在索引列上使用計算
WHERE 子句中,若是索引列是計算或者函數的一部分, DBMS 的優化器將不
會使用索引而使用全表掃描。
例以下面的 SQL 語句用於檢索月薪的 12 倍大於兩萬五千元的員工:
SELECT *FROM T_Employee
WHERE FSalary * 12 >25000;
因爲在大於號左邊的是 FSalary 12 的成績表達式,這樣 DBMS 的優化器將不會
使用字段 FSalary 的索引,由於 DBMS 必須對 T_Employee 表進行全表掃描,從而計算
FSalary * 12 的值,而後與 25000 進行比較。將上面的 SQL 語句修改成下面的等價寫法
DBMS 將會使用索引查找,從而大大提升了效率:
SELECT *FROM T_Employee
WHERE FSalary >25000/12;
一樣的,不能在索引列上使用函數,由於函數也是一種計算,會形成全表掃描。下
面的語句 2 就比語句 1 效率更加高。
語句 1
SELECT * FROM T_Example
WHERE ABS(FAmount)=300
語句 2SELECT * FROM T_Example
WHERE FAmount=300 OR FAmount=-300
11.UNION ALL 替換 UNION
SQL 語句須要 UNION 兩個查詢結果集合時,即便檢索結果中不會有重複的記
錄,若是使用 UNION 這兩個結果集一樣會嘗試進行合併,而後在輸出最終結果前進行
排序。
所以,若是檢索結果中不會有重複的記錄的話,應該用 UNION ALL 替代 UNION ,這
樣效率就會所以獲得提升。下面的語句 2 就比語句 1 效率更加高。
語句 1
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS1
WHERE TRAN_DATE = '20010101'
UNION
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS2
WHERE TRAN_DATE ='20010102'
語句 2
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS1
WHERE TRAN_DATE ='20010101'
UNION ALL
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS2
WHERE TRAN_DATE = '20010102'
12.避免隱式類型轉換形成的全表掃描
T_Person 表的字符串類型字段 FLevel 爲人員的級別,在 FAge 字段上建有索引。
咱們執行下面的 SQL 語句用於檢索全部級別等於 10 的員工:
SELECT FId,FAge,FName
FROM T_Person
WHERE FAge=10
在這個 SQL 語句中,將字符串類型字段 FLevel 與數值 10 進行比較,因爲在大部
分數據庫中隱式轉換類型中數值類型的優先級高於字符串類型,所以 DBMS 會對 FAge
字段進行隱式類型轉換,至關於執行了下面的 SQL 語句:
SELECT FId,FAge,FName
FROM T_Person
WHERE TO_INT(FAge)=10
因爲在索引字段上進行了計算,因此形成了索引失效而使用全表掃描。所以應將
SQL 語句作以下修改:
SELECT FId,FAge,FName
FROM T_Person
WHERE FAge='10'
13.防止檢索範圍過寬
若是 DBMS 優化器認爲檢索範圍過寬,那麼它將放棄索引查找而使用全表掃描。
下面是幾種可能形成檢索範圍過寬的狀況:
使用 IS NOT NULL 或者不等於判斷,可能形成優化器假設匹配的記錄數太多。
使用 LIKE 運算符的時候, "a%" 將會使用索引,而 "a%c" "%c" 則會使用全表掃描,因
"a%c" "%c" 不能被有效的評估匹配的數量。
14.事務
若是要執行一系列的操做,而這些操做最終是以總體的原子操做的形式完成的話,
事務就是必須的。關於事務的理論中,銀行轉帳問題是最經典的例子:當把錢從一個銀
行賬號轉移至另一個銀行賬號的時候,這個操做要由兩個步驟來完成,首先要將資金
從一個銀行賬號取出,而後再將其存入另外一個銀行賬號。若是資金已經從一個銀行賬號
取出了,在將資金存入另外一個銀行賬號以前或者進行當中發生異常狀況 ( 包括程序內部
異常、服務器當機、目標賬號被凍結 ) ,若是沒有事務保護就會出現源賬號中的資金已
經減小了,可是目標賬號中的資金並無增長的情況。
事務是關鍵業務系統開發中很是關鍵性的服務,對於關鍵性業務系統若是沒有采用事
務,那麼這個系統能夠說是不可用的。
相關文章
相關標籤/搜索