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

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

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

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

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

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

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

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

先看一個(gè)反面教材:

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
);

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

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

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

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

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

什么是規(guī)范化?

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

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

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

例子:

錯(cuò)誤設(shè)計(jì):

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è)計(jì):

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

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

好的命名就像一本說明書,讓團(tuán)隊(duì)協(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
  • 時(shí)間字段:統(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í)踐:

數(shù)據(jù)類型適用場景示例避免的錯(cuò)誤
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ā)計(jì)數(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需要日期和時(shí)間created_at DATETIME用字符串存時(shí)間
TIMESTAMP需要自動(dòng)更新的時(shí)間戳updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP混淆DATETIME和TIMESTAMP
ENUM固定選項(xiàng)(謹(jǐn)慎使用)status ENUM('pending','paid','shipped')選項(xiàng)經(jīng)常變化的場景
JSON確實(shí)需要存儲(chǔ)結(jié)構(gòu)化但不常查詢的數(shù)據(jù)config JSON代替關(guān)系型設(shè)計(jì)

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

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

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

基本原則:

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

常見場景:

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

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

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

索引使用注意事項(xiàng):

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

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

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

DELETE FROM users WHERE id = 1001;

軟刪除: 標(biāo)記記錄為已刪除,實(shí)際數(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ì):

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

什么情況下用軟刪除?

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

什么情況下用硬刪除?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

需求分析:

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

設(shè)計(jì)思路:

實(shí)體分析:用戶、文章、評(píng)論、點(diǎn)贊

關(guān)系分析

  • 一個(gè)用戶可以有多條評(píng)論
  • 一條評(píng)論屬于一篇文章
  • 一條評(píng)論可以有多個(gè)回復(fù)
  • 一條評(píng)論可以有多個(gè)點(diǎn)贊

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

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 '評(píng)論數(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 '評(píng)論用戶ID',
    parent_id BIGINT DEFAULT 0 COMMENT '父評(píng)論ID,0表示一級(jí)評(píng)論',
    content VARCHAR(1000) NOT NULL COMMENT '評(píng)論內(nèi)容',
    like_count INT DEFAULT 0 COMMENT '點(diǎn)贊數(shù)量',
    depth TINYINT DEFAULT 1 COMMENT '評(píng)論深度,1表示一級(jí)評(píng)論',
    path VARCHAR(255) DEFAULT '' COMMENT '路徑,格式: 0,10,25 表示層級(jí)關(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='評(píng)論表';

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='評(píng)論點(diǎn)贊表';

設(shè)計(jì)說明:

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

查詢所有一級(jí)評(píng)論及直接回復(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è)計(jì)既支持高效查詢,又能適應(yīng)業(yè)務(wù)變化,是經(jīng)過實(shí)戰(zhàn)檢驗(yàn)的可靠方案。

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

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

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

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)隊(duì)協(xié)作的基石
  • 類型要精準(zhǔn):根據(jù)實(shí)際需求選擇最合適的數(shù)據(jù)類型
  • 索引要克制:只為必要的查詢條件創(chuàng)建索引
  • 軟刪除更安全:核心業(yè)務(wù)數(shù)據(jù)優(yōu)先考慮軟刪除
  • 為未來留余地:考慮擴(kuò)展性,但不要過度設(shè)計(jì)
  • 文檔不可少:每個(gè)表、每個(gè)字段都要有清晰的注釋

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評(píng)論

商水县| 大渡口区| 民勤县| 乌审旗| 宾阳县| 出国| 利津县| 甘孜县| 昌吉市| 郓城县| 安国市| 寻甸| 井冈山市| 兴隆县| 调兵山市| 余江县| 高唐县| 安仁县| 彭阳县| 锦州市| 嘉定区| 宣城市| 扶余县| 阿拉善右旗| 杭州市| 钟山县| 枣阳市| 邻水| 徐闻县| 石渠县| 宜都市| 普陀区| 大洼县| 区。| 甘孜县| 齐河县| 乌海市| 布拖县| 绍兴县| 买车| 商水县|