年初,便制定計劃,今年主要學習數據庫的相關優化,過程中既有sybase數據庫,也有mysql,oracle的學習。以下除特殊説明外,其他涉及優化不針對某一具體數據庫,現總結相關的設計調優如下,總體我分以下幾個方面介紹我理解的數據庫設計:

1.數據庫(表,字段)設計

2.反規範

3.數據庫設備使用

4.索引使用優化

5.分表技術

6.讀寫分離

7.存儲過程


 

一  數據庫(表,字段)設計

     這個主要是一個整體的設計,如我們公司的XX數據庫,採用在審和審結庫分離,每類案件類型擁有自己獨立的數據庫作為在審庫,所有審結案件放到一個數據庫中作為審結庫。而在XX數據庫中,則採用一個業務庫包含所有案件類型的在審和審結記錄。當然這時最簡單的舉例。這裏更多的是考慮業務需求的邏輯,以及系統的實現方式。

     一個系統設計之初,設計構架人員應該會設計好整個系統需要考慮設計哪些庫,哪些表,庫表的關係,表採用什麼引擎(MYSQL),表上字段的約束,字段類型,長度,鎖模式,是否滿足一定的範式等。

二  反範式

     首先説下範式。一般情況下,系統數據庫表設計應滿足3NF,即表中不要有冗餘數據, 就是説,表的信息,如果能夠被推導出來,就不應該單獨的設計一個字段來存放. 但是,沒有冗餘的數據庫未必是最好的數據庫,有時為了提高運行效率,就必須降低範式標準,適當保留冗餘數據。具體做法是: 在概念數據模型設計時遵守第三範式,降低範式標準的工作放到物理數據模型設計時考慮。降低範式就是增加字段,允許冗餘。也就是用空間來換取時間,把數據冗餘在多個表中,當查詢時可以減少或者是避免表之間的關聯;

     如我們現在要對一個學校的課程表進行操作,現在有兩張表,一張是學生信息student(a_id,a_name,a_adress,b_id)表,一張是課程表 subject(b_id,b_subject),現在我們需要一個這樣的信息,把選擇每個課程的的課程名稱和學生姓名輸出來:

SQL語句為:select  B.b_id,B.b_subject,A_a_name from student A ,subject B;

當上面的數據量不多時,我們這樣去查詢沒有問題;當我們的兩張表的數據都是在百萬級的時候,我們去查上面的信息, 問題出現了,這個查詢動不動就是幾百毫秒,甚至更慢,這樣的查詢效率根本不能滿足我們對於網頁速度的要求(一般不能超過100毫秒),怎麼辦?當然要反範式,在課程表裏面添加冗餘字段——學生姓名,這樣我們就可以通過下面的查詢達到同樣的目的:

SQL語句為:select  b_id,b_subject,a_name from subject B;

將兩個查詢放在一起查看執行計劃,就會發現,第一個查詢開銷佔了92%,而第二個才8%,也就是説,第二個查詢比起第一個查詢,效率上優化了10倍以上,成果顯著啊。

總結:當我們開始着手一個項目後,範式的應用是這樣的變化的:第三範式數據庫的設計—–>當數據量越來越大,達到百萬級時,經常要對一些多表數據進行大範圍高頻率進行操作——->範式數據庫的設計———->網站的數據量再持續增長———->範式和反範式的數據庫設計。

三  數據庫設備使用

    仔細安排數據庫、表和索引的物理存放位置可以提高系統的性能,尤其對於需要執行大量I/O的多用户系統和多CPU系統。

以sybase為例説明下,首先應明白物理設備,段,表分區的概念。

1.跨磁盤分佈數據,避免I/O競爭

  • 將有關鍵性能要求的數據庫放置到單獨的設備上;如果可能,使用不同控制器;必要時,對關鍵表使用段,對並行查詢使用分區。
  • 將頻繁使用的表放到單獨的設備上
  • 將頻繁連接的表放到單獨的設備上
  • 使用段,將表和索引放到不同的設備上

2.從數據庫I/O隔離服務器I/O

  • tempdb放置位置
  • 單獨的最快的磁盤
  • 某些UNIX使用操作系統文件
  • sybsecurity放置位置

3.將事務日誌放在單獨的磁盤上

  • 通過減少I/O爭用提高性能
  • 確保數據硬盤崩潰能夠完全恢復
  • 加快恢復速度,因為同時異步預取請求可以在日誌設備和數據設備上預先讀取,而不會發生爭用。

4.磁盤I/O的優化

  • 查詢數據時的Logical Read(2),Physical Read(18)

       Logical Read:指從cache中或磁盤中讀取一次數據

       Physical Read:指從磁盤中讀取一次數據  (以頁-2k 為單位,當採用大塊I/O時則是2,4,或8頁)。

  • 若Physical Read次數=0 表示cache命中率為100%
  • 當採用2kI/O時 Physical Read次數= Logical Read次數 ,表示cache命中率為0
  • 優化的目標是減小I/O-尤其是物理I/O的次數-提高cache命中率
  • 對磁盤I/O問題的標識可以使用statistics io和sp_sysmon

四  索引的使用優化

1.索引使用中常見的問題

  • 表上沒有索引
  • 表上的索引不是很有用,優化器沒有使用
  • 索引不支持範圍查詢,必須使用全表掃描
  • 表上索引太多
  • 索引項太大

2.建立聚集索引的基本思想

  • 大多數表應該有聚集索引或者使用分區,以減少最後一頁的競爭。
  • 如果要對錶經常做插入操作,聚集索引不要放在具有單調上升值的列,否則會引起封鎖衝突。
  • 如果聚集索引的碼值與範圍查詢的搜索變量匹配,能提供很好的性能。
  • 聚集索引不要包括經常修改的列。
  • 選擇聚集索引應基於where子句和連接操作類型。

3.何時考慮創建非聚集索引

  • 滿足查詢條件的數據不超過20%
  • 能實現 index covering
  • 用於集函數、連接、group by和order by的列
  • 要權衡索引對查詢速度的加快與降低修改速度之間的利弊。

4.其它應注意的事項

  • 如果索引值是唯一的,要定義成唯一性索引,這樣優化器就知道對於一搜索變量只返回一行結果。
  • 如果在數據庫設計時使用了參照完整性,則被參照的列必須有唯一索引。
  • 在一經常做插入操作的表上建索引時,使用fillfactor來減少頁分裂,同時提高併發度降低死鎖的發生。
  • 如果在只讀表上建索引,則可把fillfactor置為100。
  • 索引項儘量小

5.索引的維護

  • 定期監控索引的使用
  • 刪除影響性能的索引 
  • 索引統計信息的維護
  • 重建索引