淺談MySQL表結構設計

本文首發於我的微信公衆號《andyqian》,期待您的關注!

前言

  有一小陣子沒有更新技術文章了,今天咱們繼續MySQL系列,今天要說的是MySQL表結構設計。在個人工做經歷當中,就踩過不少這方面的坑,在以前的文章《MySQL表設計踩過的坑!》中,也談到了一些坑,但總有一種,只是指出了問題,卻沒有給出解決方案的感受,今天咱們就來說講MySQL表如何設計才能避免踩坑。數據庫

選擇合適的存儲引擎

  在表結構設計中,首先咱們就要選擇一個合適的存儲引擎,咱們在以前的文章《談談MySQL存儲引擎》就簡述了每一個存儲引擎的區別,在選擇存儲引擎時,咱們應該根據本身的業務場景來選型存儲引擎,如:須要OLTP(在線事務處理)的應用,就應該選擇InnoDB存儲引擎,若是僅僅用做存儲數據,容許數據不一致,數據倉庫等場景時,可用MyISAM存儲引擎,若是你不知道如何選擇,那麼使用InnoDB存儲引擎就對了。微信

選擇合適的字符集

  這裏以前也說過一次了,主要是爲了保存emoji表情,例如: 微信暱稱,就有不少帶有emoji表情的,這裏咱們使用utf8mb4字符集,千萬不要使用blob類型來存儲。架構

主/外鍵類型

  衆所周知,主鍵的設定是很是重要的,在主鍵的選擇上,應該知足如下幾個條件:性能

  1. 惟一性   (必要條件)spa

  2. 非空性.net

  3. 有序性設計

  4. 可讀性3d

  5. 可擴展性code

主鍵的惟一性和非空性,就很少說了,其中有序性就有很多好處。例如: 查詢時,爲有序IO,就可提升查詢效率,存儲的順序也是有序的,往遠了看,分庫分表也是有好處的。所以,我建議使8字節無符號的bigint(20)做爲主鍵的數據類型
以下:中間件

create table t_base_user(
id bigint(20) unsigned not null primary key auto_increment;
....
)

這裏有幾個注意點:

  1. 主外鍵的數據類型必定要一致!

  2. 每一個表中的主鍵命名保持一致!

(我就吃過這種細節上的虧)。

無符號與有符號的區別:
  有符號容許存儲負數,無符號只容許從正數,無符號最小值爲0,最大值根據類型不一樣而不一樣。

 如下爲各個int類型的範圍:

問題一: 爲何不使用varchar類型做主鍵

答: varchar類型會對性能有影響,其中varchar也不是有序的,可讀性也很差,這裏不建議使用。
(以前我就用過UUID做爲主鍵,可讀性簡直了….當時數據量較小,還感受不到性能)。

PS: 主鍵實際上是一個比較大的話題,爲何這麼說呢,其實上面的方案也是有缺點的,適用於主從架構,對於多主呢?此時的主鍵是否是就會有重複的狀況產生了,這也就是爲何一些大廠有本身的ID生成中間件的緣由了,這裏不作深刻討論,咱們下次單獨寫一篇文章來講。

外鍵約束

  外鍵約束用來保證數據完整性的,這一點我很贊同,可是我不建議在數據庫表中加外鍵約束,由於在數據表中添加外鍵約束,會影響性能,例如: 每一次修改數據時,都要在另外的一張表中執行查詢。個人建議是:在應用層,也就是代碼層面,來維持外鍵關係。

選擇合適的類型

  這裏指的是數據列的數據類型,在選擇合適的數據類型時,咱們應知足如下條件:

  1. 儘可能選擇小,簡單的數據類型。

  2. 保持可讀性。

  3. 儘可能避免Null

咱們儘量選擇小的數據類型,這樣會有不少好處,好比服務端處理效率,傳輸等都會快些。這裏給出幾個常見的數據類型設計:

  • 狀態類型用 tinyint,例如 性別等。

  • 時間日期使用datetime,timesamp類型,我比較喜歡使用datetime類型,(可讀性高些)。

  • 儘可能不要使用text和blob數據類型,特別是blob,

設計邏輯刪除

  這個字段主要用做業務上的邏輯刪除,在如今數據爲金的時代,數據不建議作物理刪除。緣由有如下幾點:

  • 可恢復,物理刪除一旦刪除,即不可恢復。

  • 邏輯刪除數據可用數據分析等。

例如:

deleted tinyint not null default 0;

建立時間&修改時間

  這些主要是用做業務上的字段,每一個表中都應該有,在查詢,以及問題查找定位時有諸多好處,例如: 查詢最近三個月的登陸用戶,這時就可用建立時間來查詢等等,

如:

created_time datetime not null default now();

updated_time datetime not null default now() comment ''

添加合適的索引

  索引說過不少次了,這裏就再也不詳細說了,可參考以前的文章《寫會MySQL索引》,這裏須要強調的是:我建議在建立時間上都加上索引。

添加註釋

  添加註釋,這是很是重要的,其中包括表註釋,字段註釋。主要是爲了後期表結構的維護,我相信你對着數據表中那麼多字段,若是沒有註釋的話,你是很難一會兒明白是什麼意思的,即便你是該表結構的設計者,十天半個月過去後,你還記得嗎?

簡單實例:

create table t_base_user(
 id bigint(20) UNSIGNED not null primary key auto_increment comment "主鍵",
 name varchar(50) character set utf8mb4 comment "",
 created_time datetime not null default now() comment "建立時間",
 updated_time datetime not null default now() comment "修改時間",
 deleted tinyint not null default 0 comment "邏輯刪除 0正常數據 1刪除數據"
)engine=innodb charset=utf8 comment "用戶表";

//添加索引

alter table t_base_user idx_created_time(created_time);

以上表結構僅做演示,實際表結構設計時,會更復雜些,但思路是同樣的。

小結:  

下面精簡一下:

  • 選擇合適的存儲引擎,通常使用InnoDB。

  • 選擇合適的字符集,無emoji使用utf8,有emoji使用utf8mb4。

  • 主鍵使用bigint(20),主外鍵類型一致。

  • 選擇合適的類型。

  • 添加邏輯刪除,建立,修改時間。

  • 添加表,字段註釋

  • 添加索引

以上是表結構設計時的一些注意事項,能夠說是我在MySQL表結構設計的一點點積累吧,在這裏拋磚引玉了,有不一樣意見的小夥伴,均可在留言區留言,咱們旨在設計好一個不給本身挖坑的表結構。

 

相關閱讀:

談談MySQL顯示類型轉換

十個實用MySQL命令

說說 MySQL JSON 數據類型

MySQL事務隔離級別

 

這裏寫圖片描述

掃碼關注,一塊兒進步

我的博客: http://www.andyqian.com

相關文章
相關標籤/搜索