1. 程式人生 > >資料庫的設計總結

資料庫的設計總結

首先對資料庫的整體結構進行圖形化的設計,然後在依據圖形對資料庫結構進行建立。簡單來說,資料庫設計就是根據業務系統的具體需要,結合我們所選用的DBMS(資料庫管理系統),為這個業務系統構造出最優的資料儲存模型,並建立好資料庫中的表結構及表與表之間的關聯關係的過程。使之能有效的對應用系統中的資料進行儲存,並可以高效的對已經儲存的資料進行訪問。  應用系統中的資料可以有多種儲存方式,可以把所有資料儲存在一張表中,但是這樣就不能達到高效訪問的目的。

為什麼要進行資料庫設計?

好的設計:減少資料多餘,避免資料維護異常,節約儲存空間,高效的訪問 壞的設計:存在大量資料多餘,存在資料插入、更新、刪除異常,浪費大量儲存空間,訪問資料低效。  如果資料庫已經在生產環境運行了一段時間之後,在想對資料庫進行調整,就會影響業務的正常執行,所以在最初就要設計出簡潔、高效的資料結構。

設計步驟:

1.需求分析:資料是什麼,資料有哪些屬性,資料和屬性各自的特點有哪些; 2.使用ER圖對資料庫進行邏輯建模(跟我們所選的具體的資料庫管理系統是沒有關係的),大部分的表關係也是在這一步完成的 3.物理設計:根據資料庫自身的的特點把邏輯設計轉換為物理設計; 4.維護優化:新的需求進行建表,索引優化,大表拆分。隨著應用程式上線的時間越來越久,需求越來越多,資料結構也會越來越複雜,所以在維護優化的時候也要遵循以上幾步,完了之後再進行頁面的操作,這樣保證資料結構永遠是最優的。

需求分析:

瞭解系統中所要儲存的資料  瞭解資料的儲存特點,比如有的有時效性,可以採用過期清理的方式儲存,有的沒有  瞭解資料的生命週期,可以採用分庫分表的方式儲存 小問題:

  實體及實體之間的關係(1對1,1對多,多對多),可能是一個實體對應一個表,也可能是多個實體對應一個表  實體所包含的屬性有什麼  哪些屬性或屬性的組合可以唯一標識一個實體 邏輯設計:  1將需求轉化為資料庫的邏輯模型  2通過ER圖的形式對邏輯模型進行展示  3同所選用的具體的DBMS無關 常見資料庫設計正規化:  第一正規化、第二正規化、第三正規化及BC正規化,當然還有第四及第五正規化,不過重點還是前三個正規化上,這也是目前我們大多數資料庫設計所要遵循的正規化。  第一正規化  資料庫表中的所有欄位都是單一屬性,不可再分的。這個單一屬性是由基本的資料型別所構成的,如整數、浮點型、字串等,第一正規化要求資料庫中的表都是二維表。  第二正規化  資料庫的表中不存在非關鍵欄位對任一候選關鍵欄位的部分函式依賴。部分函式依賴是指存在著組合關鍵字中的某一關鍵字決定非關鍵字的情況。所有單關鍵欄位的表都複合第二正規化。  第三正規化  第三正規化是在第二正規化的基礎之上定義的,如果資料表中不存在非關鍵欄位,對任意候選關鍵欄位的傳遞函式依賴則符合第三正規化 資料操作異常:
  1插入異常,如果某實體隨著另一個實體的存在而存在,即缺少某個實體時無法表示這個實體,那麼這個表就存在插入異常。  2.更新異常,如果更改表所對應的某個實體例項的單獨屬性時,需要將多行更新,那麼這個表存在更新異常。  3.刪除異常,如果刪除表的某一行來反映某實體例項失效時導致另一個不同實體例項資訊丟失,那這個表存在刪除異常。  4資料多餘,相同的資料在多個地方存在,或者表中的某個列可以由其他列計算得到,這樣就是表中存在資料多餘。 物理設計:  常見的的DBMS系統  Oracle/SQLServer:商業資料庫,要考慮版權問題,即成本問題  MySQL/PgSQL:開源資料庫,不需支付版權費用  功能上  Oracle:口碑好,效能高,適合大的事務操作,事務成本低,其他三個事務成本高,適合小的事務  作業系統上  SQLServer:微軟的資料庫產品,目前只支援在Windows上執行,其他三個可以在Windows或Linux  開發語言  .net語言,用SQLServer,其他語言用其他三個  適合場景  MySQL、PgSQL:適用於網際網路專案  Oracle、SQLSer:更適合企業級專案,電信、ERP系統  MYSQL:由於它是開源資料庫,只要符合他的儲存協議,任何廠商都可以實現自己的儲存引擎,比較常用的幾種:MyISAM/MRG_MYISAM/Innodb/Archive/Ndb cluster,其中使用最多的是Innodb(支援事務,支援MVCC的行級鎖,主要應用場景是事務處理),在維護上相比較其他的也好一些。  欄位型別的選擇原則:列的資料型別一方面影響資料儲存空間的開銷,另一方面也會影響資料查詢效能。當一個列可以選擇多種資料型別時,應該優先考慮數字型別,其次是日期或二進位制型別,最後是字元型別。對於相同級別的資料型別,應該優先選用佔用空間小的資料型別。

以上選擇原則主要從兩個角度考慮:  1. 在對資料庫進行比較(查詢條件、JOIN條件及排序)操作時,同樣的資料,字元處理往往比數字處理慢。  2.在資料庫中,資料處理以頁為單位,列的長度越小,利於效能提升。如,SQLServer是8K位元組一頁,MYSQL在Innodb中預設16K位元組一頁,列的長度越小,一頁所能儲存的資料量就越多,在載入相同資料量的時候,如果列越小,頁數越少,IO的效能就會提高,資料庫最大的瓶頸不是CPU,而是磁碟的IO瓶頸。 Char與Varchar的選擇  1. 如果列中要儲存的資料長度差不多是一致的,則應該考慮用char,否則應考慮用Varchar  2. 如果列中的最大資料長度小於50Byte,則一般也考慮用Char,當然,如果這個列很少用,則基於節省空間和減少IO的考慮,還是可以用Varchar  3. 一般不宜定義大於50Byte的Char型別列  不同的字元型別它的位元組長度是不一樣的,如UTF-8,每個字元佔3個位元組。 Decimal和float的選擇  1. decimal用於儲存精確資料,而Float只能用於儲存非精確資料。  2. 由於Float的儲存空間開銷一般比Decimal小(精確到7位小數只需要4個位元組,而精確到15位小數只需要8位元組)。因此,精確資料只能選擇Decimal型別,而非精確資料優先選擇Float型別。 時間型別  1. 使用Int儲存時間欄位的優缺點  優點:欄位長度比datetime小  缺點:使用不方便,要進行函式轉換  限制:只能儲存到2038-1-19 11:14:07即2^32為2147483648  2. 需要儲存的時間粒度  年月日時分秒周 如何選擇主鍵  1. 區分業務主鍵和資料庫主鍵  a) 業務主鍵用於表示業務資料,進行表與表之間的關聯  b) 資料庫主鍵為了優化資料儲存(Innodb會生成6個位元組的隱含主鍵)  2. 根據資料庫的型別,考慮主鍵是否要順序增長  有些資料庫是按主鍵的順序邏輯儲存的  3. 主鍵的欄位型別所佔空間要儘可能的小  對於使用聚集索引方式儲存的表,每個索引後都會附加主鍵資訊  避免使用外來鍵約束  外來鍵是用於保持資料完整性的一種方式,但是在高併發的網際網路中,如果我們使用外來鍵,會帶來負面影響,首先,對資料的匯入操作,如果使用外來鍵,每寫一條資料都要查是否符合外來鍵約束,是非常耗時的,尤其在高併發的時候。索引是為提高查詢效率而建立的。1.降低資料匯入的效率2增加維護成本3雖然不建議使用外來鍵約束,但是相關聯的列上一定要建立索引  避免使用觸發器  我們經常會使用觸發器來減少程式上的邏輯處理,比如在操作某張表的時候同時要記錄日誌,通常會使用觸發器的方式向一張日誌表中插入資料。對於MySQL來說,使用Innldb,雖然支援觸發器,但是每一種觸發器只支援一個,before/after……一共就需要6種觸發器,如果建立觸發器之後,在使用一些其他的工具,就會出現不能建立觸發器的情況,給維護帶來影響。如果大量使用觸發器來保證業務邏輯,業務邏輯出現變更,其他人不知道的情況下,可能會影響業務規則。1.降低資料匯入的效率2可能會出現意想不到的資料異常3使業務邏輯變得複雜。 關於預留欄位  1. 無法準確的知道預留欄位的型別  2. 無法準確地知道預留欄位中所儲存的內容  3. 後期維護預留欄位所要的成本,同增加一個欄位所需要的成本是相同的  4. 嚴禁使用預留欄位  反正規化化  反正規化化是針對正規化化而言的,是為了效能和讀取效率的考慮而適當的對第三正規化的要求進行違反,而允許存在少量的資料多餘,即用空間來換時間。  好處:1減少表的關聯數量  2.增加資料的讀取效率  3.反正規化化一定要適度  資料庫維護和優化 維護資料字典  1. 使用第三方工具對資料字典進行維護  2. 利用資料庫本身的備註欄位來維護資料字典  3匯出資料字典  維護索引  如何選擇合適的列建立索引  1出現在Where從句,Group By從句,ORDer By從句中的列  2可選擇性高的列要放到索引的前面  3索引中不要包括太長的資料型別  注意:索引並不是越多越好,過多的索引不但會降低寫效率,而且會降低讀的效率;定期維護索引碎片;在SQL語句 中不要使用強制索引關鍵字 維護表結構  1使用線上變更表結構的工具2同時對資料字典進行維護3控制表的寬度和大小  資料庫中適合的操作  1批量操作VS逐條操作:批量適合在資料庫中完成,逐條適合在程式中完成  2禁止使用Select*這樣的查詢:IO的浪費,程式可能會出錯  3控制使用使用者自定義函式:雖然函式很方便,但大量使用會對索引造成影響,使用函式,列中的索引就會不起作用  4不要使用資料庫中的全文索引:需要另外建立索引檔案對索引維護,對中文的支援不太好,如果需要,最好使用專業的搜尋引擎完成  在適當的時候對錶進行水平拆分和垂直拆分  為了控制表的寬度可以進行表的垂直拆分:當列非常多的的時候,每頁的行數就會減少,儲存的資料就少了,IO 的效率就會減小,這時可以把一張大表拆分成幾張小表,拆分原則:1經常一起查詢的列放在一起2text/blob等大欄位拆分出到附加表中,可以優化IO,同時減少SQL的複雜程度,不需要關聯操作了 表的水平拆分  為了控制表的大小可以進行表的水平拆分  每張表都有主鍵,可以利用主鍵的Hash值進行拆分