最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解MySQL數(shù)據(jù)表設(shè)計的五大黃金原則

 更新時間:2026年01月18日 09:31:23   作者:程序員大華  
這篇文章主要為大家詳細(xì)介紹了MySQL數(shù)據(jù)庫設(shè)計數(shù)據(jù)表的五大黃金原則,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以了解下

新功能要上線,產(chǎn)品經(jīng)理說要加個字段。你一看表結(jié)構(gòu),倒吸一口涼氣——這表已經(jīng)30多個字段了,而且好幾個字段還是用逗號分隔存一堆值。改還是不改?這是個問題。

類似的問題還有很多,比如:

  • 需求變更時,發(fā)現(xiàn)表結(jié)構(gòu)難以擴(kuò)展
  • 數(shù)據(jù)出現(xiàn)不一致,排查了半天才發(fā)現(xiàn)是設(shè)計缺陷
  • 同事看不懂你的表結(jié)構(gòu),溝通成本極高

其實,這些問題很大程度上都可以在數(shù)據(jù)庫設(shè)計階段解決。

一、好設(shè)計 VS 壞設(shè)計

先看一個反面教材:

CREATE TABLE user (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    phone VARCHAR(50),
    email VARCHAR(255),
    address VARCHAR(500),
    hobby VARCHAR(500),
    friend_list VARCHAR(1000),
    register_time DATETIME,
    last_login_time DATETIME,
    login_count INT,
    is_delete TINYINT
);

這個設(shè)計有什么問題?

  • 一個friend_list字段存了所有好友ID,用逗號分隔
  • hobby也是用逗號分隔的多個愛好
  • is_delete字段命名不規(guī)范
  • 所有字段都允許NULL,沒有默認(rèn)值
  • 沒有任何索引

這樣的設(shè)計,項目初期可能沒問題,但隨著數(shù)據(jù)量增長,會帶來無數(shù)麻煩。下面,我們就從幾個核心原則開始,學(xué)習(xí)正確的設(shè)計方法。

二、數(shù)據(jù)庫設(shè)計的五大黃金原則

1. 規(guī)范化設(shè)計

什么是規(guī)范化?

簡單說,就是把相關(guān)數(shù)據(jù)拆分到不同的表中,避免數(shù)據(jù)冗余和異常。

第三范式(3NF)通俗解釋:

每張表只描述一個主題,并且所有字段都必須直接依賴于主鍵。

例子:

錯誤設(shè)計:

CREATE TABLE order (
    order_id INT,
    customer_name VARCHAR(100),
    customer_phone VARCHAR(20),
    product_name VARCHAR(100),
    product_price DECIMAL(10,2),
    order_date DATETIME
);

正確設(shè)計:

CREATE TABLE customer (
    customer_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    phone VARCHAR(20) NOT NULL
);

CREATE TABLE product (
    product_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL
);

CREATE TABLE order (
    order_id INT PRIMARY KEY,
    customer_id INT NOT NULL,
    order_date DATETIME NOT NULL,
    total_amount DECIMAL(12,2) NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customer(customer_id)
);

CREATE TABLE order_item (
    item_id INT PRIMARY KEY,
    order_id INT NOT NULL,
    product_id INT NOT NULL,
    quantity INT NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    FOREIGN KEY (order_id) REFERENCES order(order_id),
    FOREIGN KEY (product_id) REFERENCES product(product_id)
);

為什么這樣做更好?

  • 當(dāng)客戶信息變更時,只需修改一處
  • 產(chǎn)品價格變化不會影響歷史訂單記錄
  • 避免了數(shù)據(jù)不一致問題
  • 查詢更高效,特別是當(dāng)需要匯總統(tǒng)計時

2. 命名規(guī)范:讓人一眼看懂

好的命名就像一本說明書,讓團(tuán)隊協(xié)作更順暢。遵循以下規(guī)則:

  • 表名:使用復(fù)數(shù)名詞,如users, orders, products
  • 字段名:使用下劃線分隔,如created_at, updated_at
  • 主鍵:統(tǒng)一使用id,或者表名_id,如user_id
  • 外鍵:使用關(guān)聯(lián)表名_id,如user_id, product_id
  • 布爾字段:使用is_has_前綴,如is_deleted, has_paid
  • 時間字段:統(tǒng)一使用created_at, updated_at, deleted_at

反例:

  • u_name, phonenumb, delFlag
  • createTime, lastModifyTime(混用駝峰和下劃線)

正例:

  • user_name, phone_number, is_deleted
  • created_at, updated_at

3. 字段類型選擇:精準(zhǔn)匹配數(shù)據(jù)

選擇合適的數(shù)據(jù)類型不僅節(jié)省空間,還能提高查詢效率。下面是一些常見場景的最佳實踐:

數(shù)據(jù)類型適用場景示例避免的錯誤
TINYINT(1)布爾值(是/否)is_active TINYINT(1) DEFAULT 1用VARCHAR存"yes"/"no"
INT一般ID、數(shù)量user_id INT, view_count INT用BIGINT存小范圍數(shù)據(jù)
BIGINT大型系統(tǒng)ID、高并發(fā)計數(shù)器order_id BIGINT小型應(yīng)用過度使用
VARCHAR(N)長度可變的字符串,N應(yīng)合理設(shè)置name VARCHAR(50)所有字符串都用VARCHAR(255)
CHAR(N)固定長度字符串country_code CHAR(2)用CHAR存變長內(nèi)容
DECIMAL(M,D)金額、精確小數(shù)price DECIMAL(10,2)用FLOAT/DOUBLE存金額
DATETIME需要日期和時間created_at DATETIME用字符串存時間
TIMESTAMP需要自動更新的時間戳updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP混淆DATETIME和TIMESTAMP
ENUM固定選項(謹(jǐn)慎使用)status ENUM('pending','paid','shipped')選項經(jīng)常變化的場景
JSON確實需要存儲結(jié)構(gòu)化但不常查詢的數(shù)據(jù)config JSON代替關(guān)系型設(shè)計

重點提醒: 金額一定要用DECIMAL,而不是FLOAT/DOUBLE!后者在計算時可能有精度丟失問題。

4. 索引設(shè)計:加速查詢

索引就像書的目錄,能讓數(shù)據(jù)庫快速定位數(shù)據(jù)。但索引不是越多越好,每個索引都會增加寫入開銷。

基本原則:

  • 為經(jīng)常用于WHERE條件的字段創(chuàng)建索引
  • 為JOIN操作的關(guān)聯(lián)字段創(chuàng)建索引
  • 為ORDER BY和GROUP BY的字段考慮索引
  • 單表索引數(shù)量不宜過多(通常不超過5個)

常見場景:

-- 用戶經(jīng)常按用戶名和郵箱搜索
CREATE INDEX idx_user_name ON users(name);
CREATE INDEX idx_user_email ON users(email);

-- 訂單表經(jīng)常按用戶ID和創(chuàng)建時間查詢
CREATE INDEX idx_order_user_time ON orders(user_id, created_at);

-- 商品表經(jīng)常按分類和價格排序
CREATE INDEX idx_product_category_price ON products(category_id, price);

索引使用注意事項:

  • 索引列不要用函數(shù)或表達(dá)式,如 WHERE YEAR(create_time)=2023
  • 避免在索引列上使用NOT、<>、!=
  • LIKE查詢中,'%xxx'不會使用索引,'xxx%'會使用
  • 聯(lián)合索引要注意最左前綴原則

5. 軟刪除 和 硬刪除:數(shù)據(jù)安全策略

硬刪除: 直接從數(shù)據(jù)庫移除記錄

DELETE FROM users WHERE id = 1001;

軟刪除: 標(biāo)記記錄為已刪除,實際數(shù)據(jù)保留在數(shù)據(jù)庫中

ALTER TABLE users ADD COLUMN is_deleted TINYINT(1) DEFAULT 0;
ALTER TABLE users ADD COLUMN deleted_at DATETIME DEFAULT NULL;

-- "刪除"操作
UPDATE users SET is_deleted = 1, deleted_at = NOW() WHERE id = 1001;

軟刪除的優(yōu)勢:

  • 數(shù)據(jù)可恢復(fù),降低誤操作風(fēng)險
  • 保留歷史記錄,便于審計
  • 保證關(guān)聯(lián)數(shù)據(jù)完整性
  • 便于數(shù)據(jù)分析

什么情況下用軟刪除?

  • 核心業(yè)務(wù)數(shù)據(jù)(用戶、訂單、交易記錄)
  • 有法律合規(guī)要求的數(shù)據(jù)
  • 需要保留歷史狀態(tài)的數(shù)據(jù)

什么情況下用硬刪除?

  • 臨時數(shù)據(jù)、緩存數(shù)據(jù)
  • 敏感數(shù)據(jù)需要徹底清除
  • 存儲空間極度緊張且數(shù)據(jù)價值低

三、高級技巧:為未來做準(zhǔn)備

1. 預(yù)留擴(kuò)展字段

為未來可能的需求變化預(yù)留一些通用字段:

ALTER TABLE users 
ADD COLUMN ext_info JSON COMMENT '擴(kuò)展信息,存儲不常用字段',
ADD COLUMN version INT DEFAULT 1 COMMENT '樂觀鎖版本號';

注意: 不要過度使用擴(kuò)展字段,它只適用于少量不常用且無需查詢的屬性。

2. 分庫分表的前期準(zhǔn)備

即使初期不需要分庫分表,也可以提前做些準(zhǔn)備:

  • 使用BIGINT作為主鍵類型
  • 避免自增ID,考慮使用雪花算法等分布式ID
  • 業(yè)務(wù)字段避免跨分片JOIN
  • 考慮按時間或業(yè)務(wù)維度設(shè)計分片鍵

3. 事務(wù)邊界設(shè)計

在設(shè)計表結(jié)構(gòu)時,就要考慮事務(wù)邊界:

-- 轉(zhuǎn)賬操作需要保證原子性
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1001;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 1002;

良好的表設(shè)計應(yīng)該讓一個業(yè)務(wù)操作盡可能在一個事務(wù)內(nèi)完成,避免分布式事務(wù)。

四、評論系統(tǒng)的設(shè)計

假設(shè)我們要設(shè)計一個文章評論系統(tǒng),支持多級評論(評論可以回復(fù)評論),應(yīng)該如何設(shè)計?

需求分析:

  • 用戶可以對文章發(fā)表評論
  • 評論可以被回復(fù),形成多級結(jié)構(gòu)
  • 需要統(tǒng)計每篇文章的評論數(shù)量
  • 需要支持點贊功能
  • 需要支持敏感詞過濾

設(shè)計思路:

實體分析:用戶、文章、評論、點贊

關(guān)系分析

  • 一個用戶可以有多條評論
  • 一條評論屬于一篇文章
  • 一條評論可以有多個回復(fù)
  • 一條評論可以有多個點贊

表結(jié)構(gòu)設(shè)計

CREATE TABLE articles (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    user_id BIGINT NOT NULL,
    comment_count INT DEFAULT 0 COMMENT '評論數(shù)量,冗余字段提高查詢效率',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    is_deleted TINYINT(1) DEFAULT 0
) COMMENT='文章表';

CREATE TABLE comments (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    article_id BIGINT NOT NULL COMMENT '所屬文章ID',
    user_id BIGINT NOT NULL COMMENT '評論用戶ID',
    parent_id BIGINT DEFAULT 0 COMMENT '父評論ID,0表示一級評論',
    content VARCHAR(1000) NOT NULL COMMENT '評論內(nèi)容',
    like_count INT DEFAULT 0 COMMENT '點贊數(shù)量',
    depth TINYINT DEFAULT 1 COMMENT '評論深度,1表示一級評論',
    path VARCHAR(255) DEFAULT '' COMMENT '路徑,格式: 0,10,25 表示層級關(guān)系',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    is_deleted TINYINT(1) DEFAULT 0,
    KEY idx_article (article_id, created_at),
    KEY idx_parent (parent_id),
    FOREIGN KEY (article_id) REFERENCES articles(id)
) COMMENT='評論表';

CREATE TABLE comment_likes (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    comment_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uniq_comment_user (comment_id, user_id),
    FOREIGN KEY (comment_id) REFERENCES comments(id)
) COMMENT='評論點贊表';

設(shè)計說明:

  • 評論表使用了parent_id + depth + path的組合,支持高效查詢評論樹
  • path字段存儲層級路徑,如0,10,25表示ID為25的評論是ID為10的評論的子評論
  • article.comment_count是冗余字段,用于避免每次查詢都COUNT
  • 點贊表使用唯一索引防止重復(fù)點贊
  • 所有表都有軟刪除標(biāo)記和時間戳

查詢所有一級評論及直接回復(fù):

SELECT c1.*, c2.* 
FROM comments c1
LEFT JOIN comments c2 ON c2.parent_id = c1.id AND c2.depth = 2
WHERE c1.article_id = 100 AND c1.depth = 1 AND c1.is_deleted = 0
ORDER BY c1.created_at DESC, c2.created_at ASC;

這種設(shè)計既支持高效查詢,又能適應(yīng)業(yè)務(wù)變化,是經(jīng)過實戰(zhàn)檢驗的可靠方案。

五、工具推薦:提高設(shè)計效率

數(shù)據(jù)庫設(shè)計工具

  • MySQL Workbench(免費)
  • Navicat Data Modeler(付費)
  • dbdiagram.io(在線免費)

SQL規(guī)范檢查

  • Alibaba Java Coding Guidelines(包含SQL規(guī)范)
  • SonarQube(支持SQL質(zhì)量檢查)

版本管理

  • Flyway
  • Liquibase
  • 一定要使用版本控制管理數(shù)據(jù)庫變更腳本!

六、總結(jié)

  • 規(guī)范化是基礎(chǔ):遵循第三范式,避免數(shù)據(jù)冗余
  • 命名要一致:統(tǒng)一的命名規(guī)范是團(tuán)隊協(xié)作的基石
  • 類型要精準(zhǔn):根據(jù)實際需求選擇最合適的數(shù)據(jù)類型
  • 索引要克制:只為必要的查詢條件創(chuàng)建索引
  • 軟刪除更安全:核心業(yè)務(wù)數(shù)據(jù)優(yōu)先考慮軟刪除
  • 為未來留余地:考慮擴(kuò)展性,但不要過度設(shè)計
  • 文檔不可少:每個表、每個字段都要有清晰的注釋

以上就是一文詳解MySQL數(shù)據(jù)表設(shè)計的五大黃金原則的詳細(xì)內(nèi)容,更多關(guān)于MySQL數(shù)據(jù)表設(shè)計的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Ubuntu下mysql安裝和操作圖文教程

    Ubuntu下mysql安裝和操作圖文教程

    這篇文章主要為大家詳細(xì)分享了Ubuntu下mysql安裝和操作圖文教程,喜歡的朋友可以參考一下
    2016-05-05
  • MySQL解壓版配置步驟詳細(xì)教程

    MySQL解壓版配置步驟詳細(xì)教程

    這篇文章主要介紹了MySQL解壓版配置步驟詳細(xì)教程的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12
  • MySQL常用的系統(tǒng)函數(shù)一覽

    MySQL常用的系統(tǒng)函數(shù)一覽

    這篇文章主要介紹了MySQL常用的系統(tǒng)函數(shù)使用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Win10系統(tǒng)下MySQL8.0.16 壓縮版下載與安裝教程圖解

    Win10系統(tǒng)下MySQL8.0.16 壓縮版下載與安裝教程圖解

    這篇文章主要介紹了Win10系統(tǒng)下MySQL8.0.16 壓縮版下載與安裝教程圖解,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考解決價值,需要的朋友可以參考下
    2019-06-06
  • MySQL中常用的字段截取和字符串截取方法

    MySQL中常用的字段截取和字符串截取方法

    在 MySQL 數(shù)據(jù)庫中,有時我們需要截取字段或字符串的一部分進(jìn)行查詢、展示或處理,本文將介紹 MySQL 中常用的字段截取和字符串截取方法,幫助你靈活處理數(shù)據(jù),需要的朋友可以參考下
    2024-01-01
  • Mysql經(jīng)典的“8小時問題”

    Mysql經(jīng)典的“8小時問題”

    MySQL 的默認(rèn)設(shè)置下,當(dāng)一個連接的空閑時間超過8小時后,MySQL 就會斷開該連接,而 c3p0 連接池則以為該被斷開的連接依然有效。
    2015-04-04
  • MySQL存儲過程中游標(biāo)循環(huán)的跳出和繼續(xù)操作示例

    MySQL存儲過程中游標(biāo)循環(huán)的跳出和繼續(xù)操作示例

    這篇文章主要介紹了MySQL存儲過程中游標(biāo)循環(huán)的跳出和繼續(xù)操作示例,解決了在MySQL存儲過程中循環(huán)時執(zhí)行游標(biāo)的一個conitnue的操作解決方法,需要的朋友可以參考下
    2014-07-07
  • MySQL讀寫分離原理詳細(xì)解析

    MySQL讀寫分離原理詳細(xì)解析

    這篇文章主要介紹了MySQL讀寫分離原理詳細(xì)解析,讀寫分離是基于主從復(fù)制來實現(xiàn)的,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-07-07
  • Mysql將字符串按照指定字符分割的正確方法

    Mysql將字符串按照指定字符分割的正確方法

    字符串分割是我們開發(fā)中經(jīng)常會遇到的一個需求,下面這篇文章主要給大家介紹了關(guān)于Mysql將字符串按照指定字符分割的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • VS2019連接mysql8.0數(shù)據(jù)庫的教程圖文詳解

    VS2019連接mysql8.0數(shù)據(jù)庫的教程圖文詳解

    這篇文章主要介紹了VS2019連接mysql8.0數(shù)據(jù)庫的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05

最新評論

闸北区| 慈利县| 罗甸县| 盱眙县| 定兴县| 泸州市| 武冈市| 房产| 道真| 枣庄市| 东平县| 施甸县| 中江县| 图木舒克市| 忻城县| 澳门| 长垣县| 四川省| 玛多县| 铜梁县| 西宁市| 昌乐县| 台北县| 手游| 建德市| 平阳县| 金湖县| 张家口市| 承德市| 准格尔旗| 平罗县| 都江堰市| 阿拉善盟| 辽宁省| 宁强县| 米易县| 密山市| 中宁县| 吉木乃县| 双桥区| 临清市|