色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

21個MySQL表設計的經驗準則

數據分析與開發 ? 來源:數據分析與開發 ? 2023-01-12 10:07 ? 次閱讀

前言

作為后端開發,我們經常需要設計數據庫表。整理了21個設計MySQL表的經驗準則,分享給大家,大家看完一定會有幫助的。

1.命名規范

數據庫表名、字段名、索引名等都需要命名規范,可讀性高(一般要求用英文),讓別人一看命名,就知道這個字段表示什么意思。

比如一個表的賬號字段,反例如下

acc_no,1_acc_no,zhanghao

正例:

account_no,account_number
  • 表名、字段名必須使用小寫字母或者數字,禁止使用數字開頭,禁止使用拼音,并且一般不使用英文縮寫。
  • 主鍵索引名為pk_字段名;唯一索引名為uk_字段名;普通索引名則為idx_字段名

2.選擇合適的字段類型

設計表時,我們需要選擇合適的字段類型,比如:

  • 盡可能選擇存儲空間小的字段類型,就好像數字類型的,從tinyint、smallint、int、bigint從左往右開始選擇
  • 小數類型如金額,則選擇 decimal,禁止使用 floatdouble
  • 如果存儲的字符串長度幾乎相等,使用 char 定長字符串類型。
  • varchar是可變長字符串,不預先分配存儲空間,長度不要超過5000
  • 如果存儲的值太大,建議字段類型修改為text,同時抽出單獨一張表,用主鍵與之對應。
  • 同一表中,所有varchar字段的長度加起來,不能大于65535. 如果有這樣的需求,請使用TEXT/LONGTEXT 類型。

3. 主鍵設計要合理

主鍵設計的話,最好不要與業務邏輯有所關聯。有些業務上的字段,比如身份證,雖然是唯一的,一些開發者喜歡用它來做主鍵,但是不是很建議哈。主鍵最好是毫無意義的一串獨立不重復的數字,比如UUID,又或者Auto_increment自增的主鍵,或者是雪花算法生成的主鍵等等;

4. 選擇合適的字段長度

先問大家一個問題,大家知道數據庫字段長度表示字符長度還是字節長度嘛?

其實在mysql中,varcharchar類型表示字符長度,而其他類型表示的長度都表示字節長度。比如char(10)表示字符長度是10,而bigint(4)表示顯示長度是4個字節,但是因為bigint實際長度是8個字節,所以bigint(4)的實際長度就是8個字節。

我們在設計表的時候,需要充分考慮一個字段的長度,比如一個用戶名字段(它的長度5~20個字符),你覺得應該設置多長呢?可以考慮設置為 username varchar(32)。字段長度一般設置為2的冪哈(也就是2的n次方)。’;

5,優先考慮邏輯刪除,而不是物理刪除

什么是物理刪除?什么是邏輯刪除?

  • 物理刪除:把數據從硬盤中刪除,可釋放存儲空間
  • 邏輯刪除:給數據添加一個字段,比如is_deleted,以標記該數據已經邏輯刪除。

物理刪除就是執行delete語句,如刪除account_no =‘666’的賬戶信息SQL如下:

deletefromaccount_info_tabwhereaccount_no='666';

邏輯刪除呢,就是這樣:

updateaccount_info_tabsetis_deleted=1whereaccount_no='666';

為什么推薦用邏輯刪除,不推薦物理刪除呢?

  • 為什么不推薦使用物理刪除,因為恢復數據很困難
  • 物理刪除會使自增主鍵不再連續
  • 核心業務表 的數據不建議做物理刪除,只適合做狀態變更。

6. 每個表都需要添加這幾個通用字段如主鍵、create_time、modifed_time等

表必備一般來說,或具備這幾個字段:

  • id:主鍵,一個表必須得有主鍵,必須
  • create_time:創建時間,必須
  • modifed_time/update_time: 修改時間,必須,更新記錄時,需要更新它
  • version : 數據記錄的版本號,用于樂觀鎖,非必須
  • remark :數據記錄備注,非必須
  • modified_by :修改人,非必須
  • creator :創建人,非必須

7. 一張表的字段不宜過多

我們建表的時候,要牢記,一張表的字段不宜過多哈,一般盡量不要超過20個字段哈。筆者記得上個公司,有伙伴設計開戶表,加了五十多個字段。。。

如果一張表的字段過多,表中保存的數據可能就會很大,查詢效率就會很低。因此,一張表不要設計太多字段哈,如果業務需求,實在需要很多字段,可以把一張大的表,拆成多張小的表,它們的主鍵相同即可。

當表的字段數非常多時,可以將表分成兩張表,一張作為條件查詢表,一張作為詳細內容表 (主要是為了性能考慮)。

8. 盡可能使用not null定義字段

如果沒有特殊的理由, 一般都建議將字段定義為 NOT NULL

為什么呢?

  • 首先, NOT NULL 可以防止出現空指針問題。
  • 其次,NULL值存儲也需要額外的空間的,它也會導致比較運算更為復雜,使優化器難以優化SQL。
  • NULL值有可能會導致索引失效
  • 如果將字段默認設置成一個空字符串或常量值并沒有什么不同,且都不會影響到應用邏輯, 那就可以將這個字段設置為NOT NULL

9. 設計表時,評估哪些字段需要加索引

首先,評估你的表數據量。如果你的表數據量只有一百幾十行,就沒有必要加索引。否則設計表的時候,如果有查詢條件的字段,一般就需要建立索引。但是索引也不能濫用:

  • 索引也不要建得太多,一般單表索引個數不要超過5個。因為創建過多的索引,會降低寫得速度。
  • 區分度不高的字段,不能加索引,如性別等
  • 索引創建完后,還是要注意避免索引失效的情況,如使用mysql的內置函數,會導致索引失效的
  • 索引過多的話,可以通過聯合索引的話方式來優化。然后的話,索引還有一些規則,如覆蓋索引,最左匹配原則等等。。

假設你新建一張用戶表,如下:

CREATETABLEuser_info_tab(
`id`int(11)NOTNULLAUTO_INCREMENT,
`user_id`int(11)NOTNULL,
`age`int(11)DEFAULTNULL,
`name`varchar(255)NOTNULL,
`create_time`datetimeNOTNULL,
`modifed_time`datetimeNOTNULL,
PRIMARYKEY(`id`)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

對于這張表,很可能會有根據user_id或者name查詢用戶信息,并且,user_id是唯一的。因此,你是可以給user_id加上唯一索引,name加上普通索引。

CREATETABLEuser_info_tab(
`id`int(11)NOTNULLAUTO_INCREMENT,
`user_id`int(11)NOTNULL,
`age`int(11)DEFAULTNULL,
`name`varchar(255)NOTNULL,
`create_time`datetimeNOTNULL,
`modifed_time`datetimeNOTNULL,
PRIMARYKEY(`id`),
KEY`idx_name`(`name`)USINGBTREE,
UNIQUEKEYun_user_id(user_id)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

10. 不需要嚴格遵守 3NF,通過業務字段冗余來減少表關聯

什么是數據庫三范式(3NF),大家是否還有印象嗎?

  • 第一范式:對屬性的原子性,要求屬性具有原子性,不可再分解;
  • 第二范式:對記錄的唯一性,要求記錄有唯一標識,即實體的唯一性,即不存在部分依賴;
  • 第三方式:對字段的冗余性,要求任何字段不能由其他字段派生出來,它要求字段沒有冗余,即不存在傳遞依賴;

我們設計表及其字段之間的關系, 應盡量滿足第三范式。但是有時候,可以適當冗余,來提高效率。比如以下這張表

商品名稱 商品型號 單價 數量 總金額
手機 華為 8000 5 40000

以上這張存放商品信息的基本表。總金額這個字段的存在,表明該表的設計不滿足第三范式,因為總金額可以由單價*數量得到,說明總金額是冗余字段。但是,增加總金額這個冗余字段,可以提高查詢統計的速度,這就是以空間換時間的作法。

當然,這只是個小例子哈,大家開發設計的時候,要結合具體業務分析哈。

11. 避免使用MySQL保留字

如果庫名、表名、字段名等屬性含有保留字時,SQL語句必須用反引號來引用屬性名稱,這將使得SQL語句書寫、SHELL腳本中變量的轉義等變得非常復雜。

因此,我們一般避免使用MySQL保留字,如select、interval、desc等等

12. 不搞外鍵關聯,一般都在代碼維護

什么是外鍵呢?

外鍵,也叫FOREIGN KEY,它是用于將兩個表連接在一起的鍵。FOREIGN KEY是一個表中的一個字段(或字段集合),它引用另一個表中的PRIMARY KEY。它是用來保證數據的一致性和完整性的。

阿里的Java規范也有這么一條:

【強制】不得使用外鍵與級聯,一切外鍵概念必須在應用層解決。

我們為什么不推薦使用外鍵呢?

  • 使用外鍵存在性能問題、并發死鎖問題、使用起來不方便等等。每次做DELETE或者UPDATE都必須考慮外鍵約束,會導致開發的時候很難受,測試數據造數據也不方便。
  • 還有一個場景不能使用外鍵,就是分庫分表。

13. 一般都選擇INNODB存儲引擎

建表是需要選擇存儲引擎的,我們一般都選擇INNODB存儲引擎,除非讀寫比率小于1%, 才考慮使用MyISAM

有些小伙伴可能會有疑惑,不是還有MEMORY等其他存儲引擎嗎?什么時候使用它呢?其實其他存儲引擎一般除了都建議在DBA的指導下使用。

我們來復習一下這MySQL這三種存儲引擎的對比區別吧:

特性 INNODB MyISAM MEMORY
事務安全 支持
存儲限制 64TB
空間使用
內存使用
插入數據速度
是否支持外鍵 支持

14. 選擇合適統一的字符集。

數據庫庫、表、開發程序等都需要統一字符集,通常中英文環境用utf8

MySQL支持的字符集有utf8、utf8mb4、GBK、latin1等。

  • utf8:支持中英文混合場景,國際通過,3個字節長度
  • utf8mb4: 完全兼容utf8,4個字節長度,一般存儲emoji表情需要用到它。
  • GBK :支持中文,但是不支持國際通用字符集,2個字節長度
  • latin1:MySQL默認字符集,1個字節長度

15. 如果你的數據庫字段是枚舉類型的,需要在comment注釋清楚

如果你設計的數據庫字段是枚舉類型的話,就需要在comment后面注釋清楚每個枚舉的意思,以便于維護

正例如下:

`session_status`varchar(2)COLLATEutf8_binNOTNULLCOMMENT'session授權態00:在線-授權態有效01:下線-授權態失效02:下線-主動退出03:下線-在別處被登錄'

反例:

`session_status`varchar(2)COLLATEutf8_binNOTNULLCOMMENT'session授權態'

并且,如果你的枚舉類型在未來的版本有增加修改的話,也需要同時維護到comment后面。

16.時間的類型選擇

我們設計表的時候,一般都需要加通用時間的字段,如create_time、modified_time等等。那對于時間的類型,我們該如何選擇呢?

對于MySQL來說,主要有date、datetime、time、timestamp 和 year

  • date :表示的日期值, 格式yyyy-mm-dd,范圍1000-01-01 到 9999-12-31,3字節
  • time :表示的時間值,格式 hhss,范圍-83859 到 83859,3字節
  • datetime:表示的日期時間值,格式yyyy-mm-dd hhss,范圍1000-01-01 0000到9999-12-31 2359```,8字節,跟時區無關
  • timestamp:表示的時間戳值,格式為yyyymmddhhmmss,范圍1970-01-01 0001到2038-01-19 0307,4字節,跟時區有關
  • year:年份值,格式為yyyy。范圍1901到2155,1字節

推薦優先使用datetime類型來保存日期和時間,因為存儲范圍更大,且跟時區無關。

17. 不建議使用Stored procedure (包括存儲過程,觸發器) 。

什么是存儲過程

已預編譯為一個可執行過程的一個或多個SQL語句。

什么是觸發器

觸發器,指一段代碼,當觸發某個事件時,自動執行這些代碼。使用場景:

  • 可以通過數據庫中的相關表實現級聯更改。
  • 實時監控某張表中的某個字段的更改而需要做出相應的處理。
  • 例如可以生成某些業務的編號。
  • 注意不要濫用,否則會造成數據庫及應用程序的維護困難。

對于MYSQL來說,存儲過程、觸發器等還不是很成熟, 并沒有完善的出錯記錄處理,不建議使用。

18. 1:N 關系的設計

日常開發中,1對多的關系應該是非常常見的。比如一個班級有多個學生,一個部門有多個員工等等。這種的建表原則就是:在從表(N的這一方)創建一個字段,以字段作為外鍵指向主表(1的這一方)的主鍵。示意圖如下:

3a236b64-9198-11ed-bfe3-dac502259ad0.png

學生表是多(N)的一方,會有個字段class_id保存班級表的主鍵。當然,一班不加外鍵約束哈,只是單純保存這個關系而已。

有時候兩張表存在N:N關系時,我們應該消除這種關系。通過增加第三張表,把N:N修改為兩個 1:N。比如圖書和讀者,是一個典型的多對多的關系。一本書可以被多個讀者借,一個讀者又可以借多本書。我們就可以設計一個借書表,包含圖書表的主鍵,以及讀者的主鍵,以及借還標記等字段。

19. 大字段

設計表的時候,我們尤其需要關注一些大字段,即占用較多存儲空間的字段。比如用來記錄用戶評論的字段,又或者記錄博客內容的字段,又或者保存合同數據的字段。如果直接把表字段設計成text類型的話,就會浪費存儲空間,查詢效率也不好。

在MySQl中,這種方式保存的設計方案,其實是不太合理的。這種非常大的數據,可以保存到mongodb中,然后,在業務表保存對應mongodbid即可。

這種設計思想類似于,我們表字段保存圖片時,為什么不是保存圖片內容,而是直接保存圖片url即可。

20. 考慮是否需要分庫分表

什么是分庫分表呢?

  • 分庫:就是一個數據庫分成多個數據庫,部署到不同機器。
3a36054e-9198-11ed-bfe3-dac502259ad0.png
  • 分表:就是一個數據庫表分成多個表。
3a51cad6-9198-11ed-bfe3-dac502259ad0.png

我們在設計表的時候,其實可以提前估算一下,是否需要做分庫分表。比如一些用戶信息,未來可能數據量到達百萬設置千萬的話,就可以提前考慮分庫分表。

為什么需要分庫分表: 數據量太大的話,SQL的查詢就會變慢。如果一個查詢SQL沒命中索引,千百萬數據量級別的表可能會拖垮整個數據庫。即使SQL命中了索引,如果表的數據量超過一千萬的話,查詢也是會明顯變慢的。這是因為索引一般是B+樹結構,數據千萬級別的話,B+樹的高度會增高,查詢就變慢啦。

分庫分表主要有水平拆分、垂直拆分的說法,拆分策略有range范圍、hash取模。而分庫分表主要有這些問題:

  • 事務問題
  • 跨庫關聯
  • 排序問題
  • 分頁問題
  • 分布式ID

21. sqL 編寫的一些優化經驗

最后的話,跟大家聊來一些寫SQL的經驗吧:

  • 查詢SQL盡量不要使用select *,而是select具體字段
  • 如果知道查詢結果只有一條或者只要最大/最小一條記錄,建議用limit 1
  • 應盡量避免在where子句中使用or來連接條件
  • 注意優化limit深分頁問題
  • 使用where條件限定要查詢的數據,避免返回多余的行
  • 盡量避免在索引列上使用mysql的內置函數
  • 應盡量避免在 where子句中對字段進行表達式操作
  • 應盡量避免在where 子句中使用!=<>操作符
  • 使用聯合索引時,注意索引列的順序,一般遵循最左匹配原則。
  • 對查詢進行優化,應考慮在where 及 order by涉及的列上建立索引
  • 如果插入數據過多,考慮批量插入
  • 在適當的時候,使用覆蓋索引
  • 使用explain 分析你SQL的計劃


審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • SQL
    SQL
    +關注

    關注

    1

    文章

    766

    瀏覽量

    44161
  • 數據庫
    +關注

    關注

    7

    文章

    3816

    瀏覽量

    64449
  • MySQL
    +關注

    關注

    1

    文章

    816

    瀏覽量

    26607

原文標題:21 個 MySQL 表設計的經驗準則

文章出處:【微信號:DBDevs,微信公眾號:數據分析與開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    數據庫數據恢復—Mysql數據庫表記錄丟失的數據恢復流程

    Mysql數據庫故障: Mysql數據庫表記錄丟失。 Mysql數據庫故障表現: 1、Mysql數據庫中無任何數據或只有部分數據
    的頭像 發表于 12-16 11:05 ?171次閱讀
    數據庫數據恢復—<b class='flag-5'>Mysql</b>數據庫表記錄丟失的數據恢復流程

    MySQL還能跟上PostgreSQL的步伐嗎

    Percona 的老板 Peter Zaitsev最近發表一篇博客,討論了MySQL是否還能跟上PostgreSQL的腳步。Percona 作為MySQL 生態扛旗者,Percona 開發了知名
    的頭像 發表于 11-18 10:16 ?224次閱讀
    <b class='flag-5'>MySQL</b>還能跟上PostgreSQL的步伐嗎

    詳解MySQL多實例部署

    詳解MySQL多實例部署
    的頭像 發表于 11-11 11:10 ?264次閱讀

    MySQL編碼機制原理

    前言 一位讀者在本地部署 MySQL 測試環境時碰到一問題,我覺得挺有代表性的,所以寫篇文章介紹一下,看完相信你會對 MySQL 的編碼機制有最本質的了解,本文的目錄結構如下 讀者問題簡介
    的頭像 發表于 11-09 11:01 ?251次閱讀

    適用于MySQL的dbForge架構比較

    dbForge Schema Compare for MySQL 是一種工具,用于輕松有效地比較和部署 MySQL 數據庫結構和腳本文件夾差異。該工具提供了 MySQL 數據庫架構中所有差異的全面視圖。
    的頭像 發表于 10-28 09:41 ?219次閱讀
    適用于<b class='flag-5'>MySQL</b>的dbForge架構比較

    mysql磁盤碎片整理

    與理論上的排序順序不同,久而久之就產生了碎片。 碎片治理思路 根據線上處理經驗總結比對4種處理磁盤碎片優缺點 ? ? 治理方案 優勢 缺點 備注 將數據量巨大的設計成分區,按時間分區 通過結轉分區數據,刪除分區釋放磁盤碎片,
    的頭像 發表于 08-27 15:26 ?274次閱讀
    <b class='flag-5'>mysql</b>磁盤碎片整理

    MySQL知識點匯總

    大家好,這部分被稱為DQL部分,是每個學習MySQL必須要學會的部分,下面就讓我來介紹MySQL中的其他部分。
    的頭像 發表于 08-05 15:27 ?408次閱讀
    <b class='flag-5'>MySQL</b>知識點匯總

    華納云:如何修改MySQL的默認端口

    MySQL是世界上最流行的開源關系型數據庫管理系統之一。在某些情況下,由于安全性、網絡策略或端口沖突的原因,數據庫管理員可能需要更改MySQL服務的默認監聽端口。本文將指導您如何在不同的操作系統上
    的頭像 發表于 07-22 14:56 ?322次閱讀
    華納云:如何修改<b class='flag-5'>MySQL</b>的默認端口

    MySQL的整體邏輯架構

    支持多種存儲引擎是眾所周知的MySQL特性,也是MySQL架構的關鍵優勢之一。如果能夠理解MySQL Server與存儲引擎之間是怎樣通過API交互的,將大大有利于理解MySQL的核心
    的頭像 發表于 04-30 11:14 ?461次閱讀
    <b class='flag-5'>MySQL</b>的整體邏輯架構

    MySQL忘記root密碼解決方案

    mysql登錄密碼為password()算法加密,解密成本太高,以下為通用方案; 原理:mysql提供了特殊啟動方式,即跳過權限驗證,啟動后,登錄不需要提供密碼; 登錄后,即可修改
    的頭像 發表于 04-23 16:08 ?722次閱讀

    labview 創建mysql 時 設置時間 怎么在mysql中是格式是date 而不是datetime?

    選擇 時間日期 但是在mysql中是date而不是datetime類型 ,除了sql語句創建 ,怎么能實現創建中數據為datetime類型
    發表于 02-04 09:46

    阿里二面:了解MySQL事務底層原理嗎

    MySQL 是如何來解決臟寫這種問題的?沒錯,就是鎖。MySQL 在開啟一事務的時候,他會將某條記錄和事務做一綁定。這個其實和 JVM 鎖是類似的。
    的頭像 發表于 01-18 16:34 ?342次閱讀
    阿里二面:了解<b class='flag-5'>MySQL</b>事務底層原理嗎

    MySQL密碼忘記了怎么辦?MySQL密碼快速重置方法步驟命令示例!

    MySQL密碼忘記了怎么辦?MySQL密碼快速重置方法步驟命令示例! MySQL是一種常用的關系型數據庫管理系統,如果你忘記了MySQL的密碼,不必擔心,可以通過一些簡單的步驟來快速重
    的頭像 發表于 01-12 16:06 ?767次閱讀

    MySQL數據庫中通用空間詳解

    MySQL 數據庫中有效管理存儲和性能至關重要,通用空間為實現這一目標提供了靈活性。本文討論通用空間并探討其功能、優點和實際用法,并附有說明性示例。
    的頭像 發表于 01-10 09:33 ?2243次閱讀

    如何使用Golang連接MySQL

    首先我們來看如何使用Golang連接MySQL
    的頭像 發表于 01-08 09:42 ?3386次閱讀
    如何使用Golang連接<b class='flag-5'>MySQL</b>
    主站蜘蛛池模板: 四虎国产精品免费观看视频 | 玩两个少妇女邻居| 国内精品乱码卡一卡2卡三卡新区| 中文无码第3页不卡av| 日本中文一区| 久久久精品成人免费看| 灌饱娇嫩H将军公主最新章节| 永久免费精品精品永久-夜色| 同房交换4p好爽| 欧美最猛黑人AAAAA片| 九九热久久只有精品2| 国产成人在线免费观看| 99精品免费在线观看| 亚洲宅男天堂a在线| 无码人妻丰满熟妇啪啪网不卡| 前后灌满白浆护士| 邻家美姨在线观看全集免费| 好大好爽好深舒服死了| 各种肉黄浪荡故事集| jizzjizz丝袜| 999国产高清在线精品| 尤物久久99国产综合精品| 亚洲国产成人精品无码区APP| 色欲天天天综合网免费| 皮皮色狼网| 嗯啊快拔出来我是你老师视频| 久久久中日AB精品综合| 幻女FREE性俄罗斯学生| 国产精品人妻无码免费A片导航| 成人无码在线超碰视频| 99热这里精品| 97SE亚洲国产综合自在线不卡| 在线观看中文字幕国产| 亚洲熟妇无码乱子AV电影| 亚洲福利精品电影在线观看| 忘忧草下载| 色欲AV亚洲午夜精品无码| 日韩精品真人荷官无码| 日韩高清毛片| 色婷婷亚洲精品天天综合影院| 日本熟妇乱妇熟色A片蜜桃亚洲|