數據庫設計的一些參考(來源網上的一些帖子,僅供做者本人蔘考)

轉載自:https://blog.csdn.net/haiross/article/details/50427382html

1. 原始單據與實體之間的關係 java

  能夠是一對1、一對多、多對多的關係。在通常狀況下,它們是一對一的關係:即一張原始單據對應且只對應一個實體。 
在特殊狀況下,它們多是一對多或多對一的關係,即一張原始單證對應多個實體,或多張原始單證對應一個實體。 
這裏的實體能夠理解爲基本表。明確這種對應關係後,對咱們設計錄入界面大有好處。 

  〖例1〗:一份員工履歷資料,在人力資源信息系統中,就對應三個基本表:員工基本狀況表、社會關係表、工做簡歷表。 
        這就是「一張原始單證對應多個實體」的典型例子。 

2. 主鍵與外鍵 
  通常而言,一個實體不能既無主鍵又無外鍵。在E—R 圖中, 處於葉子部位的實體, 能夠定義主鍵,也能夠不定義主鍵 
  (由於它無子孫), 但必需要有外鍵(由於它有父親)。 

  主鍵與外鍵的設計,在全局數據庫的設計中,佔有重要地位。當全局數據庫的設計完成之後,有個美國數據庫設計專 
  家說:「鍵,處處都是鍵,除了鍵以外,什麼也沒有」,這就是他的數據庫設計經驗之談,也反映了他對信息系統核 
  心(數據模型)的高度抽象思想。由於:主鍵是實體的高度抽象,主鍵與外鍵的配對,表示實體之間的鏈接。 

3. 基本表的性質 
  基本表與中間表、臨時表不一樣,由於它具備以下四個特性: 
   (1) 原子性。基本表中的字段是不可再分解的。 
   (2) 原始性。基本表中的記錄是原始數據(基礎數據)的記錄。 
   (3) 演繹性。由基本表與代碼表中的數據,能夠派生出全部的輸出數據。 
   (4) 穩定性。基本表的結構是相對穩定的,表中的記錄是要長期保存的。 
  理解基本表的性質後,在設計數據庫時,就能將基本表與中間表、臨時表區分開來。 

4. 範式標準 
  基本表及其字段之間的關係, 應儘可能知足第三範式。 可是,知足第三範式的數據庫設計,每每不是最好的設計。 
  爲了提升數據庫的運行效率,經常須要下降範式標準:適當增長冗餘,達到以空間換時間的目的。 


  〖例2〗:有一張存放商品的基本表,如表1所示。「金額」這個字段的存在,代表該表的設計不知足第三範式, 
  由於「金額」能夠由「單價」乘以「數量」獲得,說明「金額」是冗餘字段。可是,增長「金額」這個冗餘字段, 
  能夠提升查詢統計的速度,這就是以空間換時間的做法。 
  在Rose 2002中,規定列有兩種類型:數據列和計算列。「金額」這樣的列被稱爲「計算列」,而「單價」和 
  「數量」這樣的列被稱爲「數據列」。 

  表1 商品表的表結構 
  商品名稱 商品型號 單價 數量 金額 
  電視機 29吋 2,500 40 100,000 
   
5. 通俗地理解三個範式 
  通俗地理解三個範式,對於數據庫設計大有好處。在數據庫設計中,爲了更好地應用三個範式,就必須通俗地理解 
   三個範式(通俗地理解是夠用的理解,並非最科學最準確的理解): 
  第一範式:1NF是對屬性的原子性約束,要求屬性具備原子性,不可再分解; 
  第二範式:2NF是對記錄的唯一性約束,要求記錄有唯一標識,即實體的唯一性; 
  第三範式:3NF是對字段冗餘性的約束,即任何字段不能由其餘字段派生出來,它要求字段沒有冗餘。 

  沒有冗餘的數據庫設計能夠作到。可是,沒有冗餘的數據庫未必是最好的數據庫,有時爲了提升運行效率,就必須降 
  低範式標準,適當保留冗餘數據。具體作法是:在概念數據模型設計時遵照第三範式,下降範式標準的工做放到物理 
  數據模型設計時考慮。下降範式就是增長字段,容許冗餘。 

6. 要善於識別與正確處理多對多的關係 
  若兩個實體之間存在多對多的關係,則應消除這種關係。消除的辦法是,在二者之間增長第三個實體。這樣,原來一 
  個多對多的關係,如今變爲兩個一對多的關係。要將原來兩個實體的屬性合理地分配到三個實體中去。這裏的第三個 
  實體,實質上是一個較複雜的關係,它對應一張基本表。通常來說,數據庫設計工具不能識別多對多的關係,但能處 
  理多對多的關係。 

  〖例3〗:在「圖書館信息系統」中,「圖書」是一個實體,「讀者」也是一個實體。這兩個實體之間的關係,是一 
  個典型的多對多關係:一本圖書在不一樣時間能夠被多個讀者借閱,一個讀者又能夠借多本圖書。爲此,要在兩者之 
  間增長第三個實體,該實體取名爲「借還書」,它的屬性爲:借還時間、借還標誌(0表示借書,1表示還書),另外, 
  它還應該有兩個外鍵(「圖書」的主鍵,「讀者」的主鍵),使它能與「圖書」和「讀者」鏈接。 

注視:mysql

圖書  1 和 該實體取名爲「借還書」 n 
讀者  1 和 該實體取名爲「借還書」 n 

7. 主鍵PK的取值方法 
   PK是供程序員使用的表間鏈接工具,能夠是一無物理意義的數字串, 由程序自動加1來實現。也能夠是有物理意義 
  的字段名或字段名的組合。不過前者比後者好。當PK是字段名的組合時,建議字段的個數不要太多,多了不但索引 
  佔用空間大,並且速度也慢。 

8. 正確認識數據冗餘 
  主鍵與外鍵在多表中的重複出現, 不屬於數據冗餘,這個概念必須清楚,事實上有許多人還不清楚。非鍵字段的重 
  復出現, 纔是數據冗餘!並且是一種低級冗餘,即重複性的冗餘。高級冗餘不是字段的重複出現,而是字段的派生出現。 

  〖例4〗:商品中的「單價、數量、金額」三個字段,「金額」就是由「單價」乘以「數量」派生出來的,它就是冗餘, 
  並且是一種高級冗餘。冗餘的目的是爲了提升處理速度。只有低級冗餘纔會增長數據的不一致性,由於同一數據,可 
  能從不一樣時間、地點、角色上屢次錄入。所以,咱們提倡高級冗餘(派生性冗餘),反對低級冗餘(重複性冗餘)。 

9. E--R圖沒有標準答案
 
  信息系統的E--R圖沒有標準答案,由於它的設計與畫法不是唯一的,只要它覆蓋了系統需求的業務範圍和功能內容, 
  就是可行的。反之要修改E--R圖。儘管它沒有唯一的標準答案,並不意味着能夠隨意設計。好的E—R圖的標準是: 
  結構清晰、關聯簡潔、實體個數適中、屬性分配合理、沒有低級冗餘。 

10 . 視圖技術在數據庫設計中頗有用 
  與基本表、代碼表、中間表不一樣,視圖是一種虛表,它依賴數據源的實表而存在。視圖是供程序員使用數據庫的 
  一個窗口,是基表數據綜合的一種形式, 是數據處理的一種方法,是用戶數據保密的一種手段。爲了進行復雜處理、 
  提升運算速度和節省存儲空間, 視圖的定義深度通常不得超過三層。 若三層視圖仍不夠用, 則應在視圖上定義臨時表, 
   在臨時表上再定義視圖。這樣反覆交迭定義, 視圖的深度就不受限制了。
 

  對於某些與國家政治、經濟、技術、軍事和安全利益有關的信息系統,視圖的做用更加劇要。這些系統的基本表完 
  成物理設計以後,當即在基本表上創建第一層視圖,這層視圖的個數和結構,與基本表的個數和結構是徹底相同。 
  而且規定,全部的程序員,一概只准在視圖上操做。只有數據庫管理員,帶着多我的員共同掌握的「安全鑰匙」, 
  才能直接在基本表上操做。請讀者想一想:這是爲何? 

11. 中間表、報表和臨時表 
  中間表是存放統計數據的表,它是爲數據倉庫、輸出報表或查詢結果而設計的,有時它沒有主鍵與外鍵(數據倉 
  庫除外)。臨時表是程序員我的設計的,存放臨時記錄,爲我的所用。基表和中間表由DBA維護,臨時表由程序員 
  本身用程序自動維護。 

12. 完整性約束表如今三個方面 
  域的完整性:用Check來實現約束,在數據庫設計工具中,對字段的取值範圍進行定義時,有一個Check按鈕,通 
  過它定義字段的值城。 
  參照完整性:用PK、FK、表級觸發器來實現。 
  用戶定義完整性:它是一些業務規則,用存儲過程和觸發器來實現。 

13. 防止數據庫設計打補丁的方法是「三少原則」 
   (1) 一個數據庫中表的個數越少越好。只有表的個數少了,才能說明系統的E--R圖少而精,去掉了重複的多餘的 
    實體,造成了對客觀世界的高度抽象,進行了系統的數據集成,防止了打補丁式的設計; 

   (2) 一個表中組合主鍵的字段個數越少越好。由於主鍵的做用,一是建主鍵索引,二是作爲子表的外鍵,因此組 
    合主鍵的字段個數少了,不只節省了運行時間,並且節省了索引存儲空間; 

   (3) 一個表中的字段個數越少越好。只有字段的個數少了,才能說明在系統中不存在數據重複,且不多有數據冗 
    餘,更重要的是督促讀者學會「列變行」,這樣就防止了將子表中的字段拉入到主表中去,在主表中留下許 
    多空餘的字段。所謂「列變行」,就是將主表中的一部份內容拉出去,另外單獨建一個子表。這個方法很簡 
    單,有的人就是不習慣、不採納、不執行。 

  數據庫設計的實用原則是:在數據冗餘和處理速度之間找到合適的平衡點。「三少」是一個總體概念,綜合觀點, 
  不能孤立某一個原則。該原則是相對的,不是絕對的。「三多」原則確定是錯誤的。試想:若覆蓋系統一樣的功 
  能,一百個實體(共一千個屬性) 的E--R圖,確定比二百個實體(共二千個屬性) 的E--R圖,要好得多。 

  提倡「三少」原則,是叫讀者學會利用數據庫設計技術進行系統的數據集成。數據集成的步驟是將文件系統集成 
  爲應用數據庫,將應用數據庫集成爲主題數據庫,將主題數據庫集成爲全局綜合數據庫。集成的程度越高,數據 
  共享性就越強,信息孤島現象就越少,整個企業信息系統的全局E—R圖中實體的個數、主鍵的個數、屬性的個數 
  就會越少。 

  提倡「三少」原則的目的,是防止讀者利用打補丁技術,不斷地對數據庫進行增刪改,使企業數據庫變成了隨意 
  設計數據庫表的「垃圾堆」,或數據庫表的「大雜院」,最後形成數據庫中的基本表、代碼表、中間表、臨時表 
  雜亂無章,不可勝數(即動態創表而增長表數量),致使企事業單位的信息系統沒法維護而癱瘓。 


   「三多」原則任何人均可以作到,該原則是「打補丁方法」設計數據庫的歪理學說。「三少」原則是少而精的 
  原則,它要求有較高的數據庫設計技巧與藝術,不是任何人都能作到的,由於該原則是杜絕用「打補丁方法」 
  設計數據庫的理論依據。 

14. 提升數據庫運行效率的辦法 
  在給定的系統硬件和系統軟件條件下,提升數據庫系統的運行效率的辦法是: 
   (1) 在數據庫物理設計時,下降範式,增長冗餘, 少用觸發器, 多用存儲過程。 
   (2) 當計算很是複雜、並且記錄條數很是巨大時(例如一千萬條),複雜計算要先在數據庫外面,以文件系統方 
    式用C++語言計算處理完成以後,最後才入庫追加到表中去。這是電信計費系統設計的經驗。 
   (3) 發現某個表的記錄太多,例如超過一千萬條,則要對該表進行水平分割。水平分割的作法是,以該表主鍵 
    PK的某個值爲界線,將該表的記錄水平分割爲兩個表(便可以表維護 錶行數過大 手動分割爲兩個  建個兩表union的視圖對程序透明)。若發現某個表的字段太多,例如超過八十個,則 
    垂直分割該表,將原來的一個表分解爲兩個表。 
   (4) 對數據庫管理系統DBMS進行系統優化,即優化各類系統參數,如緩衝區個數。 
   (5) 在使用面向數據的SQL語言進行程序設計時,儘可能採起優化算法。 
    總之,要提升數據庫的運行效率,必須從數據庫系統級優化、數據庫設計級優化、程序實現級優化,這三 
    個層次上同時下功夫。 


程序員

  上述十四個技巧,是許多人在大量的數據庫分析與設計實踐中,逐步總結出來的。對於這些經驗的運用,讀者不能生幫硬套,死記硬背,而要消化理解,實事求是,靈活掌握。並逐步作到:在應用中發展,在發展中應用。算法

轉載自:http://www.javaeye.com/topic/281611
sql


--------------------------------------------------------------------------------------------------------------------------數據庫

轉載自:https://www.cnblogs.com/RunForLove/p/5693986.html數組

 數據庫設計的三大範式:爲了創建冗餘較小、結構合理的數據庫,設計數據庫時必須遵循必定的規則。在關係型數據庫中這種規則就稱爲範式。範式是符合某一種設計要求的總結。要想設計一個結構合理的關係型數據庫,必須知足必定的範式。緩存

  在實際開發中最爲常見的設計範式有三個:第一範式是最基本的範式。若是數據庫表中的全部字段值都是不可分解的原子值,就說明該數據庫表知足了第一範式;第二範式在第一範式的基礎之上更進一層。第二範式須要確保數據庫表中的每一列都和主鍵相關,而不能只與主鍵的某一部分相關(主要針對聯合主鍵而言)。也就是說在一個數據庫表中,一個表中只能保存一種數據,不能夠把多種數據保存在同一張數據庫表中;第三範式須要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。總結一下,就是:第一範式(確保每列保持原子性);第二範式(確保表中的每列都和主鍵相關);第三範式(確保每列都和主鍵列直接相關,而不是間接相關)。安全

  在目前的企業信息系統中,數據庫仍是最佳的數據存儲方式,雖然已經有不少的書籍在指導咱們進行數據庫設計,但應該那種方式是設計數據庫的表結構的最好方法、設計時應聽從什麼樣的原則、四個範式如何可以用一種方式達到順暢的應用等是我一直在思考和總結的問題,下文是我針對這幾個問題根據本身的設計經歷準備總結的一篇文章的提綱,歡迎你們一塊進行探討,集思廣益。其中提到了領域建模的概念,但未做詳細解釋,但願之後可以有時間咱們針對這個命題進行深刻探討。

  1.不該該針對整個系統進行數據庫設計,而應該根據系統架構中的組件劃分,針對每一個組件所處理的業務進行組件單元的數據庫設計;不一樣組件間所對應的數據庫表之間的關聯應儘量減小,若是不一樣組件間的表須要外鍵關聯也儘可能不要建立外鍵關聯,而只是記錄關聯表的一個主鍵,確保組件對應的表之間的獨立性,爲系統或表結構的重構提供可能性。

//注意他這裏說的是"不要建立外鍵關聯",建立外鍵關聯的語句是:
//foreign key(member_id) references member (id);
//咱們幾乎沒有用到這條語句,由於咱們就是這樣作的,用到外鍵時,只是記錄關聯表的主鍵,而非在數據庫級別上建立外鍵。
//也不知道是歪打正着,仍是前輩DBA過於強大,已經考慮好了。

  2.採用領域模型驅動的方式和自頂向下的思路進行數據庫設計,首先分析系統業務,根據職責定義對象。對象要符合封裝的特性,確保與職責相關的數據項被定義在一個對象以內,這些數據項可以完整描述該職責,不會出現職責描述缺失。而且一個對象有且只有一項職責,若是一個對象要負責兩個或兩個以上的職責,應進行分拆。

// 領域模型驅動的方式,目前用的還不是很熟,考慮的不夠多。由於常常的數據庫中的表只是拿來作存儲用而已,
//特別是小需求,要加什麼字段,找到相關表加上去就好了,不太考慮領域模型。這個在中文站老業務表裏很常見

  3.根據創建的領域模型進行數據庫表的映射,此時應參考數據庫設計第二範式:一個表中的全部非關鍵字屬性都依賴於整個關鍵字。關鍵字能夠是一個屬性,也能夠是多個屬性的集合,不論那種方式,都應確保關鍵字可以保證惟一性。在肯定關鍵字時,應保證關鍵字不會參與業務且不會出現更新異常,這時,最優解決方案爲採用一個自增數值型屬性或一個隨機字符串做爲表的關鍵字。

  4.因爲第一點所述的領域模型驅動的方式設計數據庫表結構,領域模型中的每個對象只有一項職責,因此對象中的數據項不存在傳遞依賴,因此,這種思路的數據庫表結構設計從一開始即知足第三範式:一個表應知足第二範式,且屬性間不存在傳遞依賴。

//數據庫三範式記不得的同窗去查資料溫習一下。
//我的認爲第三範式的目的是儘可能減小數據冗餘,保證相同的數據只存在一份。
//第三範式其實咱們遵照的並非很嚴格,特別是老的數據庫表中會有冗餘字段。這個要看狀況決定吧。

  5.一樣,因爲對象職責的單一性以及對象之間的關係反映的是業務邏輯之間的關係,因此在領域模型中的對象存在主對象和從對象之分,從對象是從1-N或N-N的角度進一步完善主對象的業務邏輯,因此從對象及對象關係映射爲的表及表關聯關係不存在刪除和插入異常。

//最後一句看不懂,多是"因此表及表關聯關係不該該出現刪除和插入異常。"?

  6.在映射後得出的數據庫表結構中,應再根據第四範式進行進一步修改,確保不存在多值依賴。這時,應根據反向工程的思路反饋給領域模型。若是表結構中存在多值依賴,則證實領域模型中的對象具備至少兩個以上的職責,應根據第一條進行設計修正。第四範式:一個表若是知足BCNF,不該存在多值依賴。 

複製代碼
//第四範式咱們遵照的並很少吧。
//例如:
//VAS_WP_CONFIG.config_name字段的值包括:adv(廣告主題)/glare(炫彩滾動主題)/theme_simple(普通主題)/theme_cartoon(動畫主題)/ theme_none(不顯示背景主題)
//cate_background(類目背景)/video(公司視頻)/board_cartoon(動畫招牌)/board_simple(普通招牌)等。
//若是遵照第四範式,則須要新增一張VAS_WP_CONFIG_NAME表,存儲配置名稱枚舉值,而VAS_WP_CONFIG.config_name字段改成VAS_WP_CONFIG.config_name_id。
//這樣作更利於擴展,不會由於每一個人的理解不一致而向VAS_WP_CONFIG.config_name字段裏設置亂七八糟的值,可是這樣須要維護更多的小表,形成數據值表的數量膨脹,DBA可能會以爲管理上有更多的困難。
//咱們採用潛規則約定、java枚舉類等其它方式來進行保證。但有時候效果並非很好,常常發現舊數據庫表中枚舉字段的值五花八門,不全是約定的。
複製代碼

  7.在通過分析後確認全部的表都知足2、3、四範式的狀況下,表和表之間的關聯儘可能採用弱關聯以便於對錶字段和表結構的調整和重構。而且,我認爲數據庫中的表是用來持久化一個對象實例在特定時間及特定條件下的狀態的,只是一個存儲介質,因此,表和表之間也不該用強關聯來表述業務(數據間的一致性),這一職責應由系統的邏輯層來保證,這種方式也確保了系統對於不正確數據(髒數據)的兼容性。固然,從整個系統的角度來講咱們仍是要盡最大努力確保系統不會產生髒數據,單從另外一個角度來講,髒數據的產生在必定程度上也是不可避免的,咱們也要保證系統對這種狀況的容錯性。這是一個折中的方案。

  8.應針對全部表的主鍵和外鍵創建索引,有針對性的(針對一些大數據量和經常使用檢索方式)創建組合屬性的索引,提升檢索效率。雖然創建索引會消耗部分系統資源,但比較起在檢索時搜索整張表中的數據尤爲時表中的數據量較大時所帶來的性能影響,以及無索引時的排序操做所帶來的性能影響,這種方式仍然是值得提倡的。

//索引目前都是DBA根據具體的SQL來建立的,不過開發寫SQL時,也應該適當考慮一下字段的索引。

  9.儘可能少採用存儲過程,目前已經有不少技術能夠替代存儲過程的功能如"對象/關係映射"等,將數據一致性的保證放在數據庫中,不管對於版本控制、開發和部署、以及數據庫的遷移都會帶來很大的影響。但不能否認,存儲過程具備性能上的優點,因此,當系統可以使用的硬件不會獲得提高而性能又是很是重要的質量屬性時,可通過平衡考慮選用存儲過程。

//目前都是杜絕使用存儲過程的,我以爲用起來比較方便,對於咱們來講,主要緣由是會給DBA帶來管理方面的麻煩,
//由於時間一長,存儲過程的邏輯和使用場景,每每沒人能瞭解,容易產生更多問題

  10.當處理表間的關聯約束所付出的代價(經常是使用性上的代價)超過了保證不會出現修改、刪除、更改異常所付出的代價,而且數據冗餘也不是主要的問題時,表設計能夠不符合四個範式。四個範式確保了不會出現異常,但也可能由此致使過於純潔的設計,使得表結構難於使用,因此在設計時須要進行綜合判斷,但首先確保符合四個範式,而後再進行精化修正是剛剛進入數據庫設計領域時能夠採用的最好辦法。

  11.設計出的表要具備較好的使用性,主要體如今查詢時是否須要關聯多張表且還需使用複雜的SQL技巧。我感受遵照的範式越多,就越使SQL複雜,具體狀況具體分析。設計出的表要儘量減小數據冗餘,確保數據的準確性,有效的控制冗餘有助於提升數據庫的性能

  所以,考慮了以上條件以後,表設計約定規則以下:

複製代碼
//規則1:表必需要有主鍵。
//規則2:一個字段只表示一個含義。
//規則3:老是包含兩個日期字段:gmt_create(建立日期),gmt_modified(修改日期),且這兩個字段不該該包含有額外的業務邏輯。
//規則4:MySQL中,gmt_create、gmt_modified使用DATETIME類型。
//規則5:禁止使用複雜數據類型(數組,自定義類型等)。
//規則6: MySQL中,附屬表拆分後,附屬表id與主表id保持一致。不容許在附屬表新增主鍵字段。
//規則7: MySQL中,存在過時概念的表,在其設計之初就必須有過時機制,且有明確的過時時間。過時數據必須遷移至歷史表中。
//規則8: MySQL中,再也不使用的表,必須通知DBA予以改名歸檔。
//規則9: MySQL中,線上表中如有再也不使用的字段,爲保證數據完整,禁止刪除。
//規則10: MySQL中,禁止使用OCI驅動,所有使用THI驅動。
複製代碼

關於MySQL的部分學習筆記總結:

1、事務跟存儲引擎

  1.四種事務隔離級別:read uncommited, read commited(大多數db默認的),repeatable read(mysql默認), seriazable。

  2.mysql是默認的auto commited, 也就是說每次查詢默認都是自動提交的(show variables like 'autocommited')。mysql能夠經過set transaction isolatioin level命令來設置隔離級別,例如:set session transaction isolation level read commited。

  3.mysql中像innodb採用mvcc(多版本併發控制)來處理併發。mvcc只工做在read commited,repeatable read這兩種事務隔離級別上。read uncommited隔離級別不兼容mvcc是由於在該級別得下的查詢,不讀取符合當前事務版本的數據行,而是最新版本的數據行。seriazable隔離級別不兼容MVCC,由於該級別下的讀操做會對每一個返回行進行加鎖。

  4.選擇存儲引擎,併發選用myisam,事務選擇innodb,myisam比innodb更容易出錯,出錯了恢復的時間也比較長。只有myisam支持全文檢索。

  5.把表從一種存儲引擎轉到另外一種引擎:

//  1.    alter table mytable engine=falcon;  操做費時,可能會佔用服務器的全部i/o處理能力。
//  2.    create table innodb_table like myisam_table;
//        alter table innodb_table engine=innodb;
//        insert into innodb_table select * from myisam_table;

2、數據類型

  1.儘量的要把field定義爲Not NULL, mysql比較難優化使用了可空列的查詢,它會使索引,索引統計更加複雜。可空列須要更多的存儲空間,還須要mysql內部進行特殊處理,當可空列被索引時,每條記錄都須要一個格外的字節。 即便要在表中存儲"沒有值"的字段,考慮使用0,特殊字段或者空字符串來代替。

  2.datetime與timestamp能保存一樣的數據:精確度爲秒,可是timestamp使用的空間只有datetime的一半,還能保存時區,擁有特殊的自動更新能力。可是timestamp保存的時間範圍要比datetime要小得多。mysql能存儲的最細的時間粒度爲秒

  3.mysql支持不少種別名,如bool,integer,nummeric.

  4.float與double類型支持使用標準的浮點運算進行近似計算。 Decimal類型保存精確的小數,在>=mysql5.0,mysql服務器自身進行了decimal的運算,由於CPU不支持直接對它進行運算,因此慢一點。

  5.mysql會把text與blob類型的列當成有實體的對象來進行保存。他們有各自的數據類型家族(tinytext,smalltext,text,mediumtext,longtext; blob相似); mysql對blob與text列排序方式和其餘類型有所不一樣,它不會按照字符串的完整長度來排序。而只是按照max_sort_length規定的若干個字節來進行排序。

  6.採用enum來代替字符串類型。mysql在內部把每一個枚舉值都保存爲整數。enum在內部是按照數字進行排序的,而不是按照字符串。enum最很差的就是字符串列表是固定的,添加和刪除必須使用alter table。

  7.ip地址,通常會採用varchar(15)列來保存。事實上,IP地址是個無符號的32位整數,而不是字符串。mysql提供了inet_aton()和inet_nota()函數在證書與ip地址之間進行轉換。

3、索引

  1.彙集索引不只僅是一種單獨的索引類型,並且是一種存儲數據的方式。Innodb引擎的彙集索引實際上在一樣的結構中保存了B-Tree索引和數據行。當表有彙集索引時,它的數據行實際上保存在索引的葉子上。注意是存儲引擎來實現索引。

  2.myisam與innodb數據佈局:myisam索引樹(不管是主鍵索引仍是非主鍵索引)葉子節點都是指向的數據行,而innodb中彙集索引,主鍵索引樹葉子節點就帶得有數據的內容,而非主鍵索引樹中葉子節點指向主鍵值,而不是數據的位置。

  3.mysql有兩種產生排序結果的方式:使用文件排序,或者掃描有序的索引。目前只有myisam支持全文索引。

  4.myisam表有表級鎖;myisam表不支持事務,實際上,myisam並不保證單條命令完成;myisam只緩存了mysql進程內部的索引,並保存在鍵緩存區內。OS緩存了表的數據;行被緊密的保存在一塊兒,磁盤上的數據有很小的磁盤佔用和快速的全表掃描。

  5.innodb支持事務和四種事務隔離級別;在mysql5.0中,只有innodb支持外鍵;支持行級鎖與mvcc;全部的innodb表都是按照主鍵彙集的;全部索引(出開主鍵)都是按主鍵引用行;索引沒有使用前綴壓縮,所以索引可能比myisam大不少;數據轉載緩慢;阻塞auto_increment,也就是用表級鎖來產生每一個auto_increment。

4、MYSQL性能分析

  1.mysql提供了一個benchmark(int 循環次數,char* 表達式); 能夠分析表達式執行所花時間。 例如:

// select BENCHMARK(10000,SHA1('aaaaaaaaaaaaaaaa'))

  2.mysql有兩種查詢日誌:普通日誌和慢速日誌。

5、MYSQL高級特性

  1.在mysql中,只有myisam存儲引擎支持全文索引。myisam全文索引是一種特殊的具備兩層結構的B樹。

  2.存儲引擎事務在存儲引擎內部被賦予acid屬性,分佈式(XA)是一種高層次事務,它能夠歷喲內部個兩段提交的方式將acid屬性擴展到存儲引擎外部,甚至數據庫外部。階段1:通知全部提交者準備提交 階段2:通知全部參與者進行真正提交。

  3.mysql 的字符集和校對規則有 4 個級別的默認設置:服務器級、數據庫級、表級和字段級。Mysql4.1 開始支持 SQL 的子查詢。

複製代碼
/******************************************/
/*   數據庫全名 = degopen@10.218.249.92:3318【mysql】   */
/*    表名稱 = task_new   */
/******************************************/
CREATE TABLE `task_new` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `task_name` varchar(128) NOT NULL COMMENT '任務名稱',
  `image` varchar(128) DEFAULT NULL COMMENT '任務圖標',
  `description` varchar(1024) NOT NULL COMMENT '任務描述',
  `content` varchar(1024) NOT NULL COMMENT '任務內容',
  `finished_message` varchar(128) DEFAULT NULL COMMENT '任務完成提示信息',
  `task_scope` int(11) NOT NULL COMMENT '任務範圍, 0-平臺任務, 1-遊戲任務',
  `series_task` int(11) NOT NULL DEFAULT '0' COMMENT '任務類型: 系列任務,單獨任務',
  `task_type` int(11) NOT NULL DEFAULT '0' COMMENT '任務類型: 固定任務, 推廣任務, 平常任務',
  `pre_task` varchar(128) DEFAULT NULL COMMENT '前置任務',
  `post_task` varchar(128) DEFAULT NULL COMMENT '後置任務',
  `task_status` int(11) NOT NULL COMMENT '任務狀態, 待審覈、未開始、生效中、已暫停、已完成、審覈未經過',
  `auto_task` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否手動任務, 0-否, 1-是',
  `is_required` tinyint(4) NOT NULL COMMENT '是否必須任務',
  `event_type` varchar(64) DEFAULT NULL COMMENT '關心的事件類型',
  `task_target` bigint(20) DEFAULT '0' COMMENT '任務目標',
  `reset_num` int(11) NOT NULL COMMENT '重置次數',
  `reset_cycle` int(11) NOT NULL COMMENT '重置週期',
  `task_interval` int(11) NOT NULL COMMENT '任務間隔',
  `xiaoer` bigint(20) unsigned NOT NULL COMMENT '建立人',
  `review_id` bigint(20) unsigned NOT NULL COMMENT '審覈人ID',
  `last_start_time` datetime DEFAULT NULL COMMENT '上次生效時間',
  `gmt_create` datetime NOT NULL COMMENT '建立時間',
  `gmt_modified` datetime NOT NULL COMMENT '修改時間',
  `start_time` datetime NOT NULL COMMENT '開始時間',
  `end_time` datetime NOT NULL COMMENT '結束時間',
  `start_condition` varchar(1024) NOT NULL COMMENT '任務觸發條件',
  `end_condition` varchar(1024) NOT NULL COMMENT '任務完成條件',
  `enable` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否可用',
  `rule` varchar(4096) NOT NULL COMMENT '任務規則',
  `priority` int(11) NOT NULL DEFAULT '1' COMMENT '任務優先級',
  `progress_rule` varchar(2048) NOT NULL DEFAULT '' COMMENT '進度計算規則',
  `order_no` int(11) DEFAULT '1' COMMENT '排序號',
  `classification` int(11) DEFAULT '0' COMMENT '0:默認分類\n1:玩遊戲\n2:抽獎',
  `level` int(11) DEFAULT '0' COMMENT '針對同一個分類,不一樣的等級',
  `ext1` longtext COMMENT '擴展字段1(UU中使用該字段指示按鈕跳轉)',
  `ext2` longtext COMMENT '擴展字段2,暫時預留',
  `channel` int(11) DEFAULT '0' COMMENT '任務渠道:0-uu或者1-game_box',
  `consecutive_day` int(11) DEFAULT '1' COMMENT '連續完成任務的天數',
  `activity` varchar(256) DEFAULT 'default' COMMENT '任務所屬的活動名字',
  `device` text COMMENT '機型',
  `packages` text COMMENT '應用',
  PRIMARY KEY (`id`),
  KEY `name_channel` (`task_name`,`channel`),
  KEY `activity` (`activity`(255))
) ENGINE=InnoDB AUTO_INCREMENT=1194 DEFAULT CHARSET=utf8 COMMENT='任務表';
複製代碼

隨着工做經驗的積累,我日益感受到,對一名程序員來講,擁有良好的數據庫設計能力是很重要的,甚至是最重要的。

程序員界有一句著名的話

Talk is cheap, show me the code

把這句話演變一下,就成了

Code is boring, show me the data structure

面對一樣的數據結構,一百個程序員會寫出一百種風格的代碼。看別人寫的代碼,每每是很boring的。

數據結構爲什麼如此重要

代碼是圍繞數據結構運行的。

客戶端展示的動態數據,都是存儲在數據庫中,這對程序員來講必定是常識了。

爲了便於闡述,咱們拿簡書的文章頁面做爲樣板。

文章的做者、標題、正文、評論、喜歡等等,只要你打開任意兩篇文章,兩個頁面不同的地方,幾乎都是由於在數據庫中存儲的內容不一樣。

良好的數據結構能夠提高性能,使代碼變得簡單、清晰。數據結構清晰了,圍繞着數據運行的代碼天然就清晰了。

數據庫設計需考慮的因素

提到數據庫設計原則,首先會想到第1、第2、第三範式,這些理論能瞭解最好,本文再也不贅述了。

從實踐的角度面對一個具體的應用場景,設計數據庫時應遵循哪些原則?

知足當前需求

數據結構的設計要能達到應用場景的要求,這是最基本的。舉個例子,文章的正文存儲在了數據表中的某個字段,該字段的長度被設定爲10000字,在文章字數沒有被限制在10000字之內的前提下,這顯然不能知足應用場景的當前需求。須要考慮,什麼樣的字段類型才能存儲大規模的文本數據?

分離主體與附屬

文章頁面中的元素,哪些是主體部分,哪些是附屬部分?

一篇文章能夠沒有評論,評論的有無、多少不影響文章自己的完整性,評論能夠被添加、刪除。因而可知,文章的評論屬於附屬部分。閱讀次數、喜歡該文章的用戶與數量一樣如此。

主體

  • 做者
  • 標題
  • 正文(字數)
  • 發佈時間
  • 更新時間

附屬

  • 閱讀次數
  • 評論
  • 喜歡該文章的用戶與數量

拆分的好處在於,首先數據結構更清晰了,其次能夠提升讀寫性能。當文章有了新評論,只需更新存放評論的表。若是不拆分,須要更新的記錄佔用的磁盤空間很大,這對磁盤IO速度是個考驗。

適當的冗餘

或許你已經注意到了,文章的標題下面有這篇文章的字數。計算文章的字數,有兩個時機:

  • 保存文章時
  • 讀取文章時

後者的優點在於數據表中少了一個字段,並且這個字段不是必需的。哪一個時機更好?我的以爲前者更好,理由以下

  • 計算長篇文章的字數是比較耗時的,應儘可能減小計算次數
  • 整體來看,文章的保存次數遠小於讀取次數

若是可以提升應用的性能,適當的冗餘是必要的。

頁面的頭部有文章做者的暱稱,這適合做爲冗餘字段存儲在文章主體數據中嗎?用戶能夠隨時更改本身的暱稱,若是將暱稱做爲冗餘字段,須要額外的工做以保持數據一致性,從這一點看,用戶暱稱不適合做爲冗餘字段。

選擇做爲冗餘的字段應不須要額外的工做來保持數據一致性。

應對可能出現的新需求

如何存儲喜歡文章的用戶信息才能作智能推薦?一個好的數據結構應該能應對可能出現的新需求。

爲了達到應用的要求,最簡單的方式是將這些用戶放在一條記錄裏,存儲的字段能夠是數組類型。這樣設計,喜歡文章的用戶信息與用戶數量都能輕易獲取,讀寫性能也很好。但對於「喜歡該文章的人還喜歡了」此類的智能推薦,這樣的設計明顯是難以應對的。將用戶放在數組裏支持「查詢喜歡某文章的用戶」,對「查詢某用戶喜歡的文章」的支持就不好或者根本作不到了,這是一種單向查詢的數據結構。

應對大數據量

隨着用戶量不斷增長,網站業務數據愈來愈多,文章數量也達到了百萬級。這時若是隻把文章存在一張數據表裏,讀寫性能必然是會急劇降低的,這可能會致使用戶體驗變差,用戶流失。老闆不能容忍,DBA也不能容忍。

合理的解決方案之一是分爲兩張數據表,一張存儲熱門文章,另外一張存儲非熱門文章。熱門文章的佔比不多,相應的加載速度就會好於非熱門文章。

結尾

本文總結了設計數據庫時需遵照的幾個原則

  • 知足當前需求
  • 分離主體與附屬
  • 適當的冗餘
  • 應對可能出現的新需求
  • 應對大數據量

認識到數據結構的重要性,才能設計出好的數據結構。

相關文章
相關標籤/搜索