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')
語句 2:
SELECT * 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'
);
語句 2:
SELECT 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
語句 2:
SELECT * 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.事務
若是要執行一系列的操做,而這些操做最終是以總體的原子操做的形式完成的話,
事務就是必須的。關於事務的理論中,銀行轉帳問題是最經典的例子:當把錢從一個銀
行賬號轉移至另一個銀行賬號的時候,這個操做要由兩個步驟來完成,首先要將資金
從一個銀行賬號取出,而後再將其存入另外一個銀行賬號。若是資金已經從一個銀行賬號
取出了,在將資金存入另外一個銀行賬號以前或者進行當中發生異常狀況
(
包括程序內部
異常、服務器當機、目標賬號被凍結
)
,若是沒有事務保護就會出現源賬號中的資金已
經減小了,可是目標賬號中的資金並無增長的情況。
事務是關鍵業務系統開發中很是關鍵性的服務,對於關鍵性業務系統若是沒有采用事
務,那麼這個系統能夠說是不可用的。