MySQL8.0實戰(二) - 數據庫設計

0 Github

1 簡介

數據庫設計(Database Design)是指對於一個給定的應用環境,構造最優的數據庫模式,創建數據庫及其應用系統,使之可以有效地存儲數據,知足各類用戶的應用需求(信息要求和處理要求)。在數據庫領域內,經常把使用數據庫的各種系通通稱爲數據庫應用系統。 數據庫設計的設計內容包括:需求分析、概念結構設計、邏輯結構設計、物理結構設計、數據庫的實施和數據庫的運行和維護。git

2 數據庫建模五部曲

3 需求總結

◆ 課程的屬性:{主標題,副標題,方向,分類,難度最新最熱,時長,簡介,人數,需知,收穫,講師名講師職位,課程圖片綜合評分,內容實用,簡潔易懂,邏輯清晰}github

◆ 課程列表的屬性:{章名,小節名, 說明,小節時長,章節URL,視頻格式}數據庫

◆ 講師的屬性:{講師暱稱,說明,性別,省,市,職位說明,經驗,積分,關注人數,粉絲人數}bash

◆ 問答評論屬性:{類型,標題,內容,關聯章節,瀏覽量,發佈時間,用戶暱稱}數據庫設計

◆ 筆記的屬性:{用戶暱稱,關聯章節 筆記標題,筆記內容,發佈時間}。函數

◆ 用戶的屬性:{用戶暱稱密碼,說明,性別,省,市,職位,說明,經驗,積分,關注人數粉絲人數}性能

◆評價的屬性:{用戶,課程主標題,內容,綜合評分,內容實用,簡潔易懂,邏輯清晰,發佈時間}學習

4 寬表模式

  • 百度百科定義 從字面意義上講就是字段比較多的數據庫表。一般是指業務主題相關的指標、維度、屬性關聯在一塊兒的一張數據庫表。因爲把不一樣的內容都放在同一張表存儲,寬表已經不符合三範式的模型設計規範,隨之帶來的主要壞處就是數據的大量冗餘,與之相對應的好處就是查詢性能的提升與便捷。這種寬表的設計普遍應用於數據挖掘模型訓練前的數據準備,經過把相關字段放在同一張表中,能夠大大提升數據挖掘模型訓練過程當中迭代計算時的效率問題。

◆ 課程的屬性:{主標題,副標題,方向,分類難度最新,最熱,時長,簡介,人數,需知,收穫,講師名,講師職位,課程圖片綜合評分,內容實用,簡潔易懂,邏輯清晰}測試

  • 實例

4.1 模式存在的問題

4.1.1 更新異常

修改一行中某列的值時,同時修改了多行數據

例如當使用 優化

想修改其職位時,不止影響一條數據 那麼,咱們再加個限定條件
就能夠只修改一行數據,所以咱們能夠將主標題做爲該數據表的惟一標識,即主鍵! 經過主鍵更新數據,雖然能夠避免數據的更新異常,但也可能會形成表中的數據不一致現象,好比該實例中,講師的職稱就會產生多義.

4.1.2 插入異常

部分數據因爲缺失主鍵信息而沒法寫入表中

例如,咱們想新增Java開發方向的課程

因爲執行該語句時,PK爲空,即違反了PK非空且惟一的約束條件,所以該語句沒法成功.

4.1.3 刪除異常

刪除某一數據時不得不刪除另外一數據

例如,咱們想刪除數據庫方向

咱們只是單純想刪除數據庫方向而已,但該語句卻將許多課程也刪除了,這並不符合咱們的預期.

4.1.4 數據冗餘

相同的數據在一個表中出現了屢次

那麼是否是這麼多問題就意味着寬表一無可取呢?存在即合理!

4.2 模式的適用場景

配合列存儲的數據報表應用

因爲寬表中,全部數據存在於一個表中,所以在查詢時,無需多表查詢,SQL執行效率較高,且存在的上述問題在報表應用中都不是大問題

既然寬表不適合咱們的當前業務,那麼怎麼尋找合適的方法呢?

5 數據庫設計範式

5.1 第一範式

表中的全部字段都是不可再分的

例如如下實例中的聯繫方式是一個複合屬性,明顯就違反了該範式,在數據庫中是沒法分離出來的

咱們只需對其進行簡單的改動便可

即標準的二維表.

5.2 第二範式

前提

標準的二維表,即第一範式成立

表中必須存在業務主鍵,而且非主鍵依賴於所有業務主鍵

例如以下博客表實例

  • 使用用戶字段做爲PK是否可行呢? 顯然一個用戶會對應多個博客記錄,且章節標題也能爲多個用戶編輯,因此單列字段PK失效

  • 使用<用戶,章節,標題>的複合PK 然而用戶積分字段也只和用戶字段依賴,並不依賴於總體的PK,因此依舊不符合第二範式

  • 拆分將依賴的字段單獨成表

從上面,咱們也能夠發現:

  • 若表的PK只有一個字段組成,那麼它本就符合第二範式
  • 如果多個字段組成,則需考量是否符合第二範式

5.3 第三範式

表中的非主鍵列之間不能相互依賴

依舊看看課程表

首先,一個字段的PK顯然符合第二範式,大部分字段也只依賴於PK,然而對於講師職稱字段實際上是依賴於講師名的,因此不符合第三範式.

  • 將不與PK造成依賴關係的字段直接提出單獨成表便可

6 課程實體的邏輯建模

屬性

{主標題,副標題,方向,分類,難度,最新,最熱,時長,簡介,人數,需知,收穫,講師名講師職位,課程圖片綜合評分,內容實用,簡潔易懂,邏輯清晰}

咱們顯然能夠將其拆分以下:

課程表

主標題(PK),副標題,方向,分類,難度,上線時間,學習人數,時長,簡介,需知,收穫,講師暱稱,課程圖片,綜合評分,內容實用,簡潔易懂,邏輯清晰

講師表

講師名及講師的職稱

其中最新屬性即對應着上線時間計算得出,業務上可規定時間段判斷是否爲最新 最熱屬性便可以學習人數字段排序來反映

課程方向表

課程方向名稱(PK) : 在課程表中有對應的方向字段 添加時間

課程分類表

分類名稱(PK) : 在課程表中有對應的方向字段 添加時間

課程難度表

課程難度(PK) : 在課程表中有對應的方向字段 添加時間

7 課程列表實體的邏輯建模

屬性

[章節名,小節名](聯合PK) 說明,小節時長,章節URL,視頻格式

其中,說明其實只依賴於章節名 小節時長小節URL,視頻格式都只依賴於小節名 違反第二範式,因此須要拆分字段

課程章節表

章節名(PK),說明,章節編號

課程與章節的聯繫表

主標題,章節名

課程小節表

小節名稱(PK),小節視頻url,視頻格式,小節時長,小節編號

課程章節與小節的聯繫表

主標題,章節名,小節名

8 講師實體的邏輯建模

屬性

講師名,密碼,性別,省,市,職稱,說明,經驗,積分,關注數,粉絲數

講師表

講師名(PK),密碼,性別,省,市,職稱,說明,經驗,積分,關注數,粉絲數

9 用戶實體的邏輯建模

屬性

用戶暱稱,密碼,性別,省市,職位,說明,經驗,積分,關注數,粉絲數

用戶表V1.0

用戶暱稱(PK),密碼,性別,省市,職位,說明,經驗,積分,關注數,粉絲數

和講師表基本相同,且講師其實也是一種用戶,講師的信息就會被存儲兩次,形成數據的冗餘.,因而就難以保持數據一致性!考慮合併!

用戶表V2.0

用戶暱稱(PK),密碼,性別,省市,職位,說明,經驗,積分,關注數,粉絲數,講師標識

10 問答評論實體的邏輯建模

屬性

類型,標題,內容關聯章節,瀏覽量,發佈時間,用戶暱稱

其中標題文字是共享的,沒法保持一致 同一用戶在不一樣章節提出的問題也可能相同 所以決定採用標題+用戶暱稱+關聯章節做爲PK

評論表

如何記錄關聯章節字段呢? 是否是隻能用課程章節的PK來記錄呢? 所以,不得不將課程章節的關聯表PK加入

[標題,課程主標題,課程章名,小節名稱,用戶呢稱](PK) 父評論(被回覆的問題/標題) 標題,內容,類型,瀏覽量,發佈時間

11 筆記實體的邏輯建模

屬性

用戶暱稱,關聯章節,筆記標題,筆記內容,發佈時間

和評論實體差很少,分析再也不贅述

筆記表

[筆記標題,課程主標題,課程章名,小節名稱,用戶呢稱](PK) 內容,發佈時間

12 評價實體的邏輯建模

屬性

用戶呢稱;課程主標題,內容,綜合評分,內容實用,簡潔易懂,邏輯清晰,發佈時間

評價表

[用戶呢稱;課程主標題](PK) 內容,綜合評分,內容實用,簡潔易懂,邏輯清晰,發佈時間

只有選擇/購買了課程的用戶才能評價!!! 須要用戶與所選課程的關聯關係表

用戶選課表

[用戶呢稱;課程主標題](PK) 選課時間,累積聽課時長

13 小結

14 範式化暴露的問題

若是咱們想要查詢出一門課程包括全部章節和小節的相關信息

那麼這些信息又是如何存儲的呢,須要查詢哪些表呢?以下所示

咱們就要關聯5個表,查詢效率極低!且查詢課程信息的需求很大! 爲了提升性能,咱們還須要對錶結構進行優化操做

15 反範式化設計

空間換時間的思想

15.1 課程章節表反範式化設計

上述表存在一對多的關係

因此能夠並不須要關聯關係表,而是呢能夠直接把課程表和課程&章節聯繫表合併

成爲新的 課程章節表 [主標題,章節名](PK),說明,章節編號

雖然違反了第二範式,可是減小了一個表的查詢,提升了查詢性能,在頻繁查詢操做的系統中,這很值得!

通過反範式化後,咱們只須要查詢三個表便可

15.2 反範式化設計小結

課程相關表數量 5 -> 3

16 經常使用存儲引擎

17 InnoDB存儲引擎的特色

  • 事務型存儲引擎支持ACID
  • 數據按主鍵彙集存儲
  • 支持行級鎖及MVCC
  • 支持Btree和自適應Hash索引
  • 支持全文和空間索引

18 根據 InnoDB特性優化後的表邏輯結構

經過數據冗餘避免數據不一致

課程章節表:{章節ID(PK),課程ID,章節名稱,章節說明,章節編號}

課程小節表:{小節ID(PK),課程ID,章節ID,小節名稱,小節視頻url,視頻格式,小節時長,小節編號}。

課程方向表:{課程方向ID(PK),課程方向名稱,填加時間}

課程分類表:{課程分類ID(PK),分類名稱,填加時間}

課程難度表:{課程難度ID(PK) ,課程難度,填加時間}

用戶表:{用戶ID(PK),用戶暱稱,密碼,性別,省市,職位,說明,經驗,積分,關注 人數,粉絲人數,講師標識}

問答評論表:{評論ID(PK),父評論ID ,課程ID,章節ID,小節ID ,評論標題,用戶 ID,內容,類型,瀏覽量,發佈時間}

筆記表:{筆記ID(PK),課程ID,章節ID,小節ID筆記標題,用戶呢稱,筆記內容, 發佈時間}

評價表:{評價ID(PK),用戶ID,課程ID,內容綜合評分,內容實用,簡潔易懂,邏 輯清晰,發佈時間}

用戶選課表:{用戶選課ID(PK),用戶ID,課程ID,選課時間,累積聽課時長}

19 經常使用的整數類型

20 經常使用的浮點類型

  • 例如:

實戰實數類型的特色

  • 創建測試數據庫
  • 新建表
  • 插入數據至t表中

  • 查詢和
  • 和的結果
    因此只有decimal是精確的浮點類型

21 經常使用的時間類型

實戰時間類型的特色

  • 新建表

  • 插入數據

  • 查詢結果

  • 因爲北京時間是東八區,所以咱們更改時區

  • 新的查詢結果

    這就是timestamp具備時區性的特色

22 字符串類型的特色

23 如何爲數據選擇合適的的數據類型

23.1 優先選擇符合存儲數據需求的最小數據類型

INET_ATON( '255.255.255.255' ) = 4294967295
INET_ NTOA(4294967295) ='255.255.255.255'
複製代碼

23.2 謹慎使用ENUM,TEXT字符串類型

23.2.1 ENUM 的遷移

數據遷移的時候,它幾乎不可能被其餘數據庫所支持,若是 ENUM 裏面是字符串,對於其餘數據庫來講就更鬱悶了,還不能設爲tinyint等類型的字段

23.2.2 ENUM 的索引

純數字類型的不建議用枚舉類型,這是由於在 ENUM 內部維護有一個隱形的索引,也是按數字排列的,容易混淆;添加枚舉值也是一個問題,若是添加在最後還好,若是添加在中間什麼位置的話,原來的隱藏索引將再也不起做用

23.2.3 ENUM 字段 的NULL 值

ENUM 字段默認是能夠插入 NULL 值的,這個就比較尷尬了,並且沒有辦法優化

23.2.4 插入的值

若是插入的值比ENUM設定的值大,會默認保存成接近的那個值;插入的值不能包含函數,不能傳遞參數

因此若是插入的值是數字型的,建議用tinyint,若是插入的值是字符型的,建議用char。若是真想用 ENUM 也是能夠得,前提是要了解到 ENUM 的弊端,就能夠有效規避這些問題

23.4 同財務相關的數值型數據,必需使用decimal類型。

24 爲項目表們選擇合適的數據類型

24.1 課程表

24.2 章節表

24.3 小節表

24.4 課程分類表

24.5 課程難度表

24.5 課程方向表

24.6 用戶表

24.7 問答評論表

24.8 筆記表

在這裏插入圖片描述

24.9 用戶選課表

30 如何爲表和列選擇合適的名字

  • 全部數據庫對像名稱必須使用小寫字母可選用下劃線分割
  • 全部數據庫對像名稱定義禁止使用MySQL保留關建字
  • 數據庫對像的命名要能作到見名識義,而且最好不要超過32個字
  • 臨時庫表必須以tmp爲前綴並以日期爲後綴
  • 用於備份的庫,表必須以bak爲前綴並以日期爲後綴
  • 全部存儲相同數據的列名和列類型必須一致。

31 總結

工程師的必備技能

一、前奏:【業務分析】欲善其事,必三思而行; 二、高潮:【邏輯設計】範式化VS反範式化; 三、結束:【物理設計】存儲引擎&數據類型&命名規約。

內容綜述

  • 數據庫的邏輯設計規範
  • MySQL的經常使用存儲引擎及其選擇方法
  • MySQL的經常使用數據類型及其選擇方法
  • 如何爲表選擇適合的存儲類型
  • 如何爲表起一個好名

參考

數據庫設計 MySQL慎用 ENUM 字段

更多內容請關注JavaEdge公衆號

相關文章
相關標籤/搜索