資料庫優化

無陵山發表於2018-05-27

1 系統優化介紹 

在我們的專案中,由於客戶的使用時間較長或客戶的資料量大,造成系統運
行速度慢,系統效能下降就容易造成資料庫阻塞。這是個非常痛苦的事情,使用者
的查詢、新增、修改等需要花很多時間,甚至造成系統當機的現象。速度慢的原
因主要是來自於資源不足。 
資料庫的優化通常可以通過對網路、硬體、作業系統、資料庫引數和應用程
序的優化來進行。最常見的優化手段就是對硬體的升級。根據統計,對網路、硬
件、作業系統、資料庫引數進行優化所獲得的效能提升,全部加起來最多隻佔數
據庫系統效能提升的 40%左右(我將此暫時稱之為外圍優化);其餘大部分系統性
能提升來自對應用程式的優化,對於應用程式的優化可以分為對原始碼的優化及
資料庫 SQL 語句的優化。在本文件只介紹外圍優化及 SQL 語句的優化,對於源代
碼的優化需要相關方面的專家,形成統一的規範。 
一個資料庫系統的生命週期可以分成:設計、開發和成品三個階段。在設計
階段進行資料庫效能優化的成本最低,收益最大。在成品階段進行資料庫效能優
化的成本最高,收益最小。規範的程式碼和高效能的語句,功在平時,利在千秋。
 

2 外圍優化 

2.1、將作業系統與 SQL 資料庫的補丁打到最高版本,WIN2003 最高補丁是 SP4,
SQL SERVER2000 最高補丁是 SP4
2.2、在伺服器上不要安裝與 VA 程式任何無相關的軟體,甚至一些與 VA 執行
無關的服務都可以停掉。一般只安裝 SQL 資料庫、VA 服務端服務及防毒
軟體。 
2.3、防毒軟體避免對大檔案進行掃描,特別是資料庫(MDF 和 LDF)檔案,一
定要從防毒軟體的範圍內排除掉。 
2.4、在進行伺服器分割槽時,分割槽不要太多,兩三個分割槽就可以了。分割槽最好
都使用 NTFS 格式。 
2.5、定時對磁碟進行掃描和磁碟整理,減少系統檔案錯誤及減少磁碟碎片,
進行磁碟整理時最好不要使用 WINDOWS 本般的掃描功能(掃描之前一定
要對資料庫作異地備份)。 
2.6、可以考慮設定增大磁碟的快取區,減少對磁碟的讀寫次數。 
2.7、升級硬體,整機使用更高配置的硬體。或者可以單獨增加 CPU 個數、增
大記憶體等。 
2.8、提高網速。
 

3 SQL 優化 

3.1 註釋使用 
在語句中多寫註釋,註釋不影響 SQL 語句的執行效率。增加程式碼的可讀 性。 
3.2 對於事務的使用 
儘量使事務處理達到最短,如果事務太長最好按功能將事務分開執行 (如:可以讓使用者在介面上多幾步操作)。事務太長很容易造成資料庫阻塞, 使用者操作速度變慢或當機情況。 
3.3 對於與資料庫的互動 
儘量減少與資料庫的互動次數。如果在前端程式寫有循球訪問資料庫操 作,最好寫成將資料一次讀到前端再進行處理或者寫成儲存過程在資料庫 端直接處理。 
3.4 對於 SELECT *這樣的語句, 
不要使用 SELECT *這樣的語句,而應該使用 SELECT table1.column1 這 樣的語句,明確指出要查詢的列減少資料的通訊量並且這樣的程式碼可讀性 好,便於維護。 
3.5 儘量避免使用遊標 

它佔用大量的資源。如果需要 row-by-row 地執行,儘量採用非游標技術,

如:在客戶端迴圈,用臨時表,Table 變數,用子查詢,用 Case 語句等等。 如果使用了遊標,就要儘量避免在遊標迴圈中再進行表連線的操作。 
3.6 儘量使用 count(1) 
count 函式只有在統計表中所有行數時使用,而且 count(1)比 count(*)更 有效率。
 
3.7 IN 和 EXISTS 
  EXISTS 要遠比 IN 的效率高。裡面關係到 full table scan 和 range scan。 幾乎將所有的 IN 操作符子查詢改寫為使用 EXISTS 的子查詢。 
3.8 注意表之間連線的資料型別避免不同型別資料之間的連線。  
3.9 儘量少用檢視 
對檢視操作比直接對錶操作慢,可以用 stored procedure 來代替她。特別的 是不要用檢視巢狀,巢狀檢視增加了尋找原始資料的難度。我們看檢視的本 質:它是存放在伺服器上的被優化好了的已經產生了查詢規劃的 SQL。對 單個表檢索資料時,不要使用指向多個表的檢視,直接從表檢索或者僅僅 包含這個表的檢視上讀,否則增加了不必要的開銷,查詢受到干擾。 
3.10 沒有必要時不要用 DISTINCT 和 ORDER BY 
這些動作可以改在客戶端執行,它們增加了額外的開銷。 
3.11 避免相關子查詢 
一個列的標籤同時在主查詢和 where 子句中的查詢中出現,那麼很可能 當主查詢中的列值改變之後,子查詢必須重新查詢一次。查詢巢狀層次越 多,效率越低,因此應當儘量避免子查詢。如果子查詢不可避免,那麼要 在子查詢中過濾掉儘可能多的行。 
3.12 程式碼離資料越近越好 
所以優先選擇 Default,依次為 Rules,Triggers, Constraint(約束如外健主健 CheckUNIQUE……,資料型別的最大長度等等都是約束),Procedure.這樣不
僅維護工作小,編寫程式質量高,並且執行的速度快。 
3.13 插入大的二進位制值到 Image 列 
使用儲存過程,千萬不要用內嵌 Insert 來插入。因為這樣應用程式首先 將二進位制值轉換成字串(尺寸是它的兩倍),伺服器受到字元後又將他轉換 成二進位制值.儲存過程就沒有這些動作: 方法:Create procedure p_insert as insert into table(Fimage) values (@image), 在前臺呼叫這個儲存過程傳入二 進位制引數,這樣處理速度明顯改善。 
3.14 Between 在某些時候比 IN 速度更快 
Between 能夠更快地根據索引找到範圍。用查詢優化器可見到差別。 select * from chineseresume where title in (` 男 `,` 女 `) Select * from chineseresume where between `男` and `女` 是一樣的。由於 in 會在比較多次, 所以有時會慢些。 
3.15 對 Where 條件欄位修飾欄位移到右邊 
任何對列的操作都將導致表掃描,它包括資料庫函式、計算表示式等等, 查詢時要儘可能將操作移至等號右邊。 
3.16 在海量查詢時儘量少用格式轉換。 
3.17 IS NULL 與 IS NOT NULL 
  不能用 null 作索引,任何包含 null 值的列都將不會被包含在索引中。 即使索引有多列這樣的情況下,只要這些列中有一列含有 null,該列就會 從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提 高效能。任何在 where 子句中使用 is null 或 is not null 的語句優化器是不允 許使用索引的。 
3.18 建立臨時表, 
如果一次性插入資料量很大,那麼可以使用 select into 代替 create table, 避免 log,提高速度;如果資料量不大,為了緩和系統表的資源,建議先 create table,然後 insert。臨時表是 tempdb 資料庫實際的表,沒有主鍵、索引, 應該避免在臨時表中儲存大量的資料。  
3.19 Where 中索引的使用 
WHERE 條件順序儘量把索引欄位放在前面(主鍵的唯一性最高),複合 索引欄位順序與 where 條件順序保持一致。Sql 自動查詢使用那個索引。 
3.20 外來鍵關聯的列應該建立索引 
(如子表id)主子表單據肯定要建檢視, 2個表的關聯以2個表中的MainID 為關係,所以,需要給子表的 MainID 單獨建索引,這將很大地提高檢視的 速度。例如 Gy_InOutSub 中的 InoutMainid 增加索引。 
 
3.21 注意 UNion 和`UNion all 的區別 
UNION all 執行效率高。 
3.22 Insert 
Insert into 表 values() 應該為 Insert into 表 (欄位) values() 
3.23 order by 語句 
ORDER BY 語句決定了如何將返回的查詢結果排序。Order by 語句對要 排序的列沒有什麼特別的限制,也可以將函式加入列中(象聯接或者附加 等)。任何在 Order by 語句的非索引項或者有計算表示式都將降低查詢速 度。 仔細檢查 order by 語句以找出非索引項或者表示式,它們會降低效能。 解決這個問題的辦法就是重寫 order by 語句以使用索引,也可以為所使用 的列建立另外一個索引,同時應絕對避免在 order by 子句中使用表示式。

相關文章