CodeGym /課程 /SQL SELF /正規化的優點與缺點

正規化的優點與缺點

SQL SELF
等級 26 , 課堂 4
開放

今天我們再來聊聊一個很重要的主題:正規化的優點與缺點,這次會講得更細一點,讓你更懂這些概念在真實世界怎麼用。OK,繫好安全帶——我們要開始囉!

消除資料重複

當你的資料表沒正規化時,你會發現同樣的資訊會在不同的列裡重複出現。舉例來說,訂單表裡每一筆訂單都可能重複存放客戶地址。正規化就是把這些重複的資料拆到獨立的表裡。

範例:

-- 正規化前
CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_name TEXT,
    customer_address TEXT,
    order_date DATE
);

-- 正規化後
CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    customer_name TEXT,
    customer_address TEXT
);

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id),
    order_date DATE
);

為什麼這很重要?資料重複越少,出錯的機會就越低。如果客戶地址有變動,你只要改一個地方就好。

確保資料完整性

當資料被拆分到邏輯上不同的表時,管理它們的關聯就很簡單。用 foreign key 可以自動幫你維護資料完整性。比如說,你不會不小心刪掉還有訂單紀錄的客戶。

範例:

-- foreign key 保證刪掉客戶時也會把相關訂單刪掉
ALTER TABLE orders
ADD CONSTRAINT fk_customer FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE CASCADE;

你可以很放心,資料庫結構不會讓你產生「孤兒」資料。

簡化更新操作

當你的資料庫正規化後,更新資料就變得超簡單也比較不容易出錯。還記得剛剛的客戶例子嗎?如果客戶換地址,你只要改一個表裡的紀錄。沒正規化的話,你很可能會忘記改某幾列,結果資料就不一致了。

減少異常狀況

插入異常:沒正規化的表有時候會遇到沒辦法新增資料,因為缺少某些資訊。比如說,還不知道客戶名字時就不能新增訂單。

更新異常:更新資料時可能會出錯。像是只改了一列的客戶名字,其他列還是舊的。

刪除異常:刪除一筆資料時可能會連帶把重要資訊刪掉。比如說,刪掉訂單時也把客戶名字刪了,如果這些資料都在同一個表裡的話。

減少資料量

正規化通常會讓資料庫變小,因為重複的資料被消掉了。這對於要存很多資料的時候很重要。

正規化的缺點

1. 資料庫結構變複雜

正規化久了,資料庫結構可能會變得很複雜,甚至有上千個(!)關聯的表。這時候,原本一個表就能查到的資料,現在要寫很複雜的 SQL 查詢,還要用很多 JOIN

複雜度範例:

-- 查詢訂單資訊,還有商品和分類的細節
SELECT
    o.order_id,
    o.order_date,
    c.customer_name,
    p.product_name,
    cat.category_name,
    oi.quantity,
    oi.unit_price
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
JOIN categories cat ON p.category_id = cat.category_id;

如果表和關聯越來越多,查詢的時間也會變很久。

2. JOIN 太多會拖慢效能

常常 JOIN 表的話(JOIN),尤其是表很大又沒 index,會很吃資源。在做分析的系統裡,如果查詢要處理幾百萬筆資料,正規化會讓效能大打折扣。

3. 要額外做反正規化操作

如果正規化的資料庫要拿來做分析,通常要暫時反正規化,這樣查詢才會快。這可能要建立 VIEW 或是專門的彙總表。

範例:

-- 給分析用的反正規化 view
CREATE VIEW orders_with_customers AS
SELECT
    o.order_id,
    o.order_date,
    c.customer_name,
    c.customer_address
FROM
    orders o
JOIN
    customers c ON o.customer_id = c.customer_id;

4. 入門門檻高

對新手來說,正規化看起來很難。原本一個表就搞定,現在要處理好幾個表,還要搞懂它們的關聯。這會讓開發速度變慢,尤其是團隊對資料庫還不熟的時候。

5. 有時候重複資料反而比較好

在實際專案裡,有時候保留重複資料反而比較有效率。比如說,應用程式常常要用到某些資料,而這些資料要靠很複雜的 JOIN 才查得到,那還不如直接存在同一個表裡。

1
問卷/小測驗
現有資料庫分析,等級 26,課堂 4
未開放
現有資料庫分析
現有資料庫分析
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION