SQL進階之旅 Day 2:高效的表設計與規范:從基礎到實戰

【SQL進階之旅 Day 2】高效的表設計與規范:從基礎到實戰

開篇

在數據庫開發中,一個良好的表設計不僅能夠提高查詢效率,還能避免冗余數據和一致性問題。本文作為"SQL進階之旅"系列的第2天,將重點介紹高效的表設計與規范,包括主鍵、外鍵、約束以及范式的應用。我們將通過理論講解、代碼示例和實際案例,幫助你掌握這些關鍵技能。

理論基礎

1. 主鍵(Primary Key)

主鍵是用于唯一標識表中每一行記錄的字段或字段組合。主鍵必須滿足以下條件:

  • 唯一性:每個值都必須唯一。
  • 非空性:主鍵列不允許為NULL。

主鍵通常用于加速查詢操作,尤其是在頻繁進行JOIN操作時。

2. 外鍵(Foreign Key)

外鍵是指向另一個表主鍵的字段,用于維護表之間的關聯關系。外鍵約束可以防止非法數據插入,并確保引用完整性。

3. 約束(Constraints)

除了主鍵和外鍵之外,常見的約束還包括:

  • NOT NULL:字段不能為空。
  • UNIQUE:字段值必須唯一。
  • CHECK:字段值必須滿足特定條件。
  • DEFAULT:字段未指定值時使用默認值。

4. 范式(Normalization)

范式是一組規則,用于減少數據冗余并提高數據一致性。常見的范式有:

  • 第一范式(1NF):消除重復組,確保每列原子化。
  • 第二范式(2NF):在1NF基礎上,消除部分依賴。
  • 第三范式(3NF):在2NF基礎上,消除傳遞依賴。

適用場景

高效的表設計適用于以下業務場景:

  • 高頻讀寫操作的系統,如電商平臺訂單管理。
  • 數據一致性要求高的金融系統。
  • 多表關聯查詢較多的數據分析平臺。

例如,在電商系統中,如果訂單表沒有合理的主鍵和外鍵約束,可能會導致訂單重復、用戶信息不一致等問題。

代碼實踐

我們以一個簡單的電商平臺為例,展示如何設計高效的表結構。

1. 創建用戶表(users)

-- 用戶表
CREATE TABLE users (user_id INT PRIMARY KEY AUTO_INCREMENT, -- 主鍵,自動遞增username VARCHAR(50) NOT NULL UNIQUE, -- 唯一用戶名,不能為空email VARCHAR(100) NOT NULL,          -- 郵箱,不能為空created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 默認創建時間
);

2. 創建商品表(products)

-- 商品表
CREATE TABLE products (product_id INT PRIMARY KEY AUTO_INCREMENT, -- 主鍵product_name VARCHAR(100) NOT NULL,        -- 商品名稱price DECIMAL(10, 2) NOT NULL CHECK (price > 0), -- 價格必須大于0stock INT NOT NULL DEFAULT 0               -- 庫存,默認為0
);

3. 創建訂單表(orders)

-- 訂單表
CREATE TABLE orders (order_id INT PRIMARY KEY AUTO_INCREMENT,user_id INT NOT NULL,order_date DATE NOT NULL,total_amount DECIMAL(10, 2) NOT NULL,FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE -- 外鍵,級聯刪除
);

4. 創建訂單詳情表(order_details)

-- 訂單詳情表
CREATE TABLE order_details (order_detail_id INT PRIMARY KEY AUTO_INCREMENT,order_id INT NOT NULL,product_id INT NOT NULL,quantity INT NOT NULL CHECK (quantity > 0),unit_price DECIMAL(10, 2) NOT NULL,FOREIGN KEY (order_id) REFERENCES orders(order_id) ON DELETE CASCADE,FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE RESTRICT -- 限制刪除
);

5. 插入測試數據

-- 插入用戶
INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com');-- 插入商品
INSERT INTO products (product_name, price, stock) VALUES ('iPhone 14', 7999.99, 10);-- 插入訂單
INSERT INTO orders (user_id, order_date, total_amount)
VALUES (1, '2023-10-01', 7999.99);-- 插入訂單詳情
INSERT INTO order_details (order_id, product_id, quantity, unit_price)
VALUES (1, 1, 1, 7999.99);

6. 查詢示例:獲取用戶的訂單及商品信息

SELECT u.username,o.order_id,p.product_name,od.quantity,od.unit_price,(od.quantity * od.unit_price) AS total_item_price
FROM users u
JOIN orders o ON u.user_id = o.user_id
JOIN order_details od ON o.order_id = od.order_id
JOIN products p ON od.product_id = p.product_id;

執行原理

1. 主鍵索引

主鍵會自動創建一個聚簇索引(Clustered Index),使得查詢速度更快。MySQL使用InnoDB引擎時,主鍵決定了數據的物理存儲順序。

2. 外鍵約束

當插入或更新order_details表中的product_id時,數據庫會檢查products表中是否存在該ID。如果不存在,則拒絕操作。

3. JOIN操作優化

多表JOIN操作時,建議:

  • 在JOIN字段上建立索引(尤其是外鍵字段)。
  • 盡量避免在WHERE子句中對JOIN字段進行函數操作。

4. 查詢執行計劃分析

我們可以使用EXPLAIN來查看查詢執行計劃:

EXPLAIN SELECT u.username,o.order_id,p.product_name,od.quantity,od.unit_price,(od.quantity * od.unit_price) AS total_item_price
FROM users u
JOIN orders o ON u.user_id = o.user_id
JOIN order_details od ON o.order_id = od.order_id
JOIN products p ON od.product_id = p.product_id;

輸出結果如下(簡化版):

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersindexPRIMARYPRIMARY41Using index condition; Using where
1SIMPLEordersrefuser_iduser_id4example.users.user_id1Using where
1SIMPLEorder_detailsreforder_idorder_id4example.orders.order_id1Using where
1SIMPLEproductseq_refPRIMARYPRIMARY4example.order_details.product_id1NULL

從執行計劃可以看出,所有JOIN操作都使用了索引,查詢效率較高。

性能測試

1. 測試環境

  • MySQL 8.0
  • InnoDB引擎
  • 表規模:users(10萬條)、orders(50萬條)、order_details(100萬條)

2. 查詢性能對比

查詢類型平均耗時(優化前)平均耗時(優化后)
單表查詢(無索引)500ms50ms
多表JOIN查詢800ms120ms

優化手段:

  • orders.user_idorder_details.order_idorder_details.product_id上添加索引。
  • 使用覆蓋索引(Covering Index)減少回表查詢。

最佳實踐

1. 主鍵選擇

  • 使用自增整數(INT/AUTO_INCREMENT)作為主鍵,避免UUID帶來的碎片問題。
  • 對于高并發寫入場景,考慮使用BIGINT代替INT

2. 外鍵使用注意事項

  • 不要濫用外鍵,避免復雜的級聯操作影響性能。
  • 如果業務邏輯已由程序層保證,可以適當放寬外鍵約束。

3. 索引優化策略

  • 在經常查詢的字段上建立索引。
  • 對于頻繁更新的字段,避免過多索引。
  • 使用聯合索引來支持復合查詢條件。

4. 范式與反范式的權衡

  • 范式:適用于寫多讀少的系統,保證數據一致性。
  • 反范式:適用于讀多寫少的系統,減少JOIN操作。

案例分析:電商平臺訂單查詢慢的問題

問題描述

某電商平臺在高峰期發現“用戶訂單查詢”響應時間超過2秒,嚴重影響用戶體驗。

分析過程

  1. 查看SQL語句:涉及多個JOIN操作。
  2. 使用EXPLAIN分析:發現order_details表缺少索引。
  3. 添加索引后,查詢時間下降至200ms。

解決方案

  • order_details.order_id上添加索引。
  • orders.user_id也添加索引,優化JOIN效率。

總結

今天我們學習了高效的表設計與規范,包括主鍵、外鍵、約束和范式的應用。通過合理設計表結構和使用索引,我們可以顯著提升查詢性能。以下是今天學到的核心技能:

  • 如何設計主鍵和外鍵以保證數據一致性。
  • 如何使用約束確保數據質量。
  • 如何通過范式減少數據冗余。
  • 如何通過索引優化多表JOIN查詢。

下一天內容預告

明天我們將進入基礎查詢優化技巧,學習如何通過WHERE條件優化和JOIN優化進一步提升查詢性能。敬請期待!

參考資料

  1. MySQL官方文檔 - Constraints
  2. PostgreSQL官方文檔 - Constraints
  3. SQLZoo - SQL Tutorial
  4. W3Schools - SQL Tutorial
  5. High Performance MySQL

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82052.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82052.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82052.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java—— IO流的應用

帶權重的點名系統 案例要求 文件中有學生的信息,每個學生的信息獨占一行。包括學生的姓名,性別,權重 要求每次被抽中的學生,再次被抽中的概率在原先的基礎上降低一半。 本題的核心就是帶權重的隨機 分析 權重,權重和…

Docker中部署Alertmanager

在 Docker 中部署 Alertmanager(通常與 Prometheus 告警系統配合使用)的步驟如下: 一、拉取鏡像prom/alertmanager docker pull prom/alertmanager二、 創建 Alertmanager 配置文件 首先準備Alertmanager的配置文件 alertmanager.yml(如存…

【大模型面試每日一題】Day 27:自注意力機制中Q/K/V矩陣的作用與縮放因子原理

【大模型面試每日一題】Day 27:自注意力機制中Q/K/V矩陣的作用與縮放因子原理 📌 題目重現 🌟🌟 面試官:請解釋Transformer自注意力機制中Query、Key、Value矩陣的核心作用,并分析為何在計算注意力分數時…

AI+能碳管理系統:全生命周期碳管理

在"雙碳"目標的時代背景下,AI賦能的能碳管理系統正在重新定義企業碳管理的邊界與深度。這套系統猶如一位不知疲倦的碳管家,從原材料采購到產品報廢,在每一個價值環節編織起精密的碳管理網絡,實現從微觀設備到宏觀戰略的…

k8s1.27版本集群部署minio分布式

需求: 1.創建4個pv,一個pv一個minio-pod。使用sts動態分配pvc(根據存儲類找到pv)。----持久化 2.暴露minio的9001端口。(nodeport)----管理界面 鏡像:minio/minio:RELEASE.2023-03-20T20-16-18Z--->換國內源 說明…

使用 OpenCV 實現 ArUco 碼識別與坐標軸繪制

🎯 使用 OpenCV 實現 ArUco 碼識別與坐標軸繪制(含Python源碼) Aruco 是一種廣泛用于機器人、增強現實(AR)和相機標定的方形標記系統。本文將帶你一步一步使用 Python OpenCV 實現圖像中多個 ArUco 碼的檢測與坐標軸…

Qt 控件發展歷程 + 目標(1)

文章目錄 聲明簡述控件的發展歷程學習目標QWidget屬性 簡介:這篇文章只是一個引子,介紹一點與控件相關的但不重要的內容(瀏覽瀏覽即可),這一章節最為重要的還是要把之后常用且重要的控件屬性和作用給學透,學…

socc 19 echash論文部分解讀

前言:論文還是得吃透才行,不然很多細節有問題 q1 object和data chunck哪一個大 根據論文,一個 data chunk 通常比一個 object 大,因為它是由多個 object 組合而成的 。 論文中提到,cross-coding 會將多個 object 組合…

w~自動駕駛~合集1

我自己的原文哦~ https://blog.51cto.com/whaosoft/12371169 #世界模型和DriveGPT這類大模型到底能給自動駕駛帶來什么ne 以下分享大模型與自動駕駛結合的相關工作9篇論 1、ADAPT ADAPT: Action-aware Driving Caption Transformer(ICRA2023) A…

【paddle】常見的數學運算

根據提供的 PaddlePaddle 函數列表,我們可以將它們按照數學運算、邏輯運算、三角函數、特殊函數、統計函數、張量操作和其他操作等類型進行分類。以下是根據函數功能進行的分類: 取整運算 Rounding functions 代碼描述round(x)距離 x 最近的整數floor(…

繪制音頻信號的各種頻譜圖,包括Mel頻譜圖、STFT頻譜圖等。它不僅能夠繪制頻譜圖librosa.display.specshow

librosa.display.specshow 是一個非常方便的函數,用于繪制音頻信號的各種頻譜圖,包括Mel頻譜圖、STFT頻譜圖等。它不僅能夠繪制頻譜圖,還能自動設置軸標簽和刻度,使得生成的圖像更加直觀和易于理解。 ### 函數簽名 python libros…

DDR DFI 5.2 協議接口學習梳理筆記01

備注:本文新增對各種時鐘含義做了明確定義區分,避免大家產生誤解,這也是5.2版本新引入的。 1. 前言 截止2025年5月,DFI協議最新版本為 5.2,我們首先看一下過去幾代的演進: DFI全稱DDR PHY Interface,是一種接口協議,定義了 Controller 和 PHY 之間接口的信號、時序以…

windows篡改腳本提醒

? 功能簡介 該監控系統具備如下主要功能: 📁 目錄監控 實時監聽指定主目錄及其所有子目錄內文件的變動情況。 🔒 文件哈希校驗 對文件內容生成 SHA256 哈希,確保變更檢測基于內容而非時間戳。 🚫 排除機制 支…

文章記單詞 | 第102篇(六級)

一,單詞釋義 apologize /??p?l?d?a?z/ v. 道歉;認錯discharge /d?s?t?ɑ?rd?/ v./n. 排出;釋放;解雇; dischargequiver /?kw?v?r/ v./n. 顫抖;抖動;箭筒plantation /pln?te??…

【DCGMI專題1】---DCGMI 在 Ubuntu 22.04 上的深度安裝指南與原理分析(含架構圖解)

目錄 一、DCGMI 概述與應用場景 二、Ubuntu 22.04 系統準備 2.1 系統要求 2.2 環境清理(可選) 三、DCGMI 安裝步驟(詳細圖解) 3.1 安裝流程總覽 3.2 分步操作指南 3.2.1 系統更新與依賴安裝 3.2.2 添加 NVIDIA 官方倉庫 3.2.3 安裝數據中心驅動與 DCGM 3.2.4 服務…

主成分分析(PCA)法例題——給定協方差矩陣

已知樣本集合的協方差矩陣為 C x 1 10 [ 3 1 1 1 3 ? 1 1 ? 1 3 ] {\bm C}_x \frac{1}{10} \begin{bmatrix} 3 & 1 & 1 \\ 1 & 3 & -1 \\ 1 & -1 & 3 \end{bmatrix} Cx?101? ?311?13?1?1?13? ? 使用PCA方法將樣本向量降到二維 。 求解 計…

uni-app(4):js語法、css語法

1 js語法 uni-app的js API由標準ECMAScript的js API 和 uni 擴展 API 這兩部分組成。標準ECMAScript的js僅是最基礎的js。瀏覽器基于它擴展了window、document、navigator等對象。小程序也基于標準js擴展了各種wx.xx、my.xx、swan.xx的API。node也擴展了fs等模塊。uni-app基于E…

Idea 配合 devtools 依賴 實現熱部署

核心依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency> yaml配置 spring: #…

leetcode513.找樹左下角的值:遞歸深度優先搜索中的最左節點追蹤之道

一、題目本質與核心訴求解析 在二叉樹算法問題中&#xff0c;"找樹左下角的值"是一個典型的結合深度與位置判斷的問題。題目要求我們找到二叉樹中最深層最左邊的節點值&#xff0c;這里的"左下角"有兩個關鍵限定&#xff1a; 深度優先&#xff1a;必須是…

Python入門手冊:Python基礎語法

Python是一種簡潔、易讀且功能強大的編程語言&#xff0c;非常適合初學者入門。無論你是編程新手&#xff0c;還是有一定編程基礎但想學習Python的開發者&#xff0c;掌握Python的基礎語法都是邁向高效編程的第一步。本文將詳細介紹Python的基本語法&#xff0c;包括變量和數據…