標籤:

淺談SQL性能調優

淺談SQL性能調優

5 人贊了文章

a.性能調優的目的主要有以下兩點:

1.優化響應時間

何為「優化響應時間」 呢?說的通俗點,就是經過調優後,執行查詢、更新等操作的時候,資料庫的反應速度更快,花費的時間更少。

比較常見的,以前執行某條sql查詢語句,可能需要3秒鐘,加了索引後,1秒鐘不到就搞定了。加索引,這也是最典型最"廉價"的優化手段。

2.優化吞吐量

說起「吞吐量」,那就要想到「並發」了。其實就是「同時處理請求」的能力。如何提高資料庫"抗並發"的能力呢?首先要了解sqlserver是如何訪問數據的,如何控制並發訪問的(事務隔離級別,鎖等),如何與底層操作系統進行交互的,還要了解「多線程、進程」等方面的知識。

比較常見的手段,通過降低事務隔離級別(一定程度地犧牲數據一致性等),這種「軟手段」通常會起到很好的效果。其次,單台DB Server達到一定瓶頸後,可以通過「集群」等方式,實現請求的「負載均衡」的,來達到「抗並發」的目的,效果也是立竿見影的。

b.下面就優化響應時間做仔細分析

1:創建必要的索引

在經常需要進行檢索的欄位上創建索引,比如要按照姓名進行檢索,那麼就應該在姓名欄位上創建索引,如果經常要按照員工部門和員工崗位級別進行檢索,那麼就應該在員工部門和員工崗位級別這兩個欄位上創建索引。創建索引給檢索帶來的性能提升往往是巨大的,因此在發現檢索速度過慢的時候應該首先想到的就是創建索引。

2:使用預編譯查詢

程序中通常是根據用戶的輸入來動態執行SQL,這時應該盡量使用參數化SQL,這樣不僅可以避免SQL注入漏洞攻擊,最重要資料庫會對這些參數化SQL進行預編譯,這樣第一次執行的時候DBMS會為這個SQL語句進行查詢優化並且執行預編譯,這樣以後再執行這個SQL的時候就直接使用預編譯的結果,這樣可以大大提高執行的速度。

3:調整Where字句中的連接順序

DBMS一般採用自下而上的順序解析where字句,根據這個原理表連接最好寫在其他where條件之前,那些可以過濾掉最大數量記錄。

4:盡量將多條SQL語句壓縮到一句

SQL中每次執行SQL的時候都要建立網路連接、進行許可權校驗、進行SQL語句的查詢優化、發送執行結果,這個過程是非常耗時的,因此應該盡量避免過多的執行SQL語句,能夠壓縮到一句SQL執行的語句就不要用多條來執行。

5:用where字句替換HAVING字句

避免使用HAVING字句,因為HAVING只會在檢索出所有記錄之後才對結果集進行過濾,而where則是在聚合前刷選記錄,如果能通過where字句限制記錄的數目,那就能減少這方面的開銷。HAVING中的條件一般用於聚合函數的過濾,除此之外,應該將條件寫在where字句中。

6:使用表的別名

當在SQL語句中連接多個表時,請使用表的別名並把別名前綴於每個列名上。這樣就可以減少解析的時間並減少哪些友列名歧義引起的語法錯誤。

7:在in和exists中通常情況下使用EXISTS,因為in不走索引。

8:避免在索引上使用計算

在where字句中,如果索引列是計算或者函數的一部分,DBMS的優化器將不會使用索引而使用全表查詢,函數屬於計算的一種

效率低:select * from Employee where dsalary*12>2500.0(dsalary是索引列,索引不起作用)

效率高:select * from Employee where dsalary>2500.0/12(dsalary是索引列)

9:用union all替換union

當SQL語句需要union兩個查詢結果集合時,即使檢索結果中不會有重複的記錄,如果使用union這兩個結果集同樣會嘗試進行合併,然後在輸出最終結果前進行排序,因此如果可以判斷檢索結果中不會有重複的記錄時候,應該用union all,這樣效率就會因此得到提高。

10:避免SQL中出現隱式類型轉換

當某一張表中的索引欄位在作為where條件的時候,如果進行了隱式類型轉換,則此索引欄位將會不被識別,因為隱式類型轉換也屬於計算,所以此時DBMS會使用全表掃面。

11:防止檢索範圍過寬

如果DBMS優化器認為檢索範圍過寬,那麼將放棄索引查找而使用全表掃描。下面幾種可能造成檢索範圍過寬的情況。

a、使用is not null或者不等於判斷,可能造成優化器假設匹配的記錄數太多。

b、使用like運算符的時候,「a%」將會使用索引,而「a%c」和「%a」則會使用全表掃描,因此「a%c」和「%a」不能被有效的評估匹配的數量,舉例:

給strEmpName創建索引

select * from Employee where strEmpName like a%(索引起作用)

select * from Employee where strEmpName like a%b(索引不起作用)

select * from Employee where strEmpName like %a(索引不起作用)


推薦閱讀:

sql優化
SQL注入攻防入門詳解

TAG:SQL優化 |