當架構師開始設計資料結構時,注意力往往集中在連接上。我們會特別關注實體及其相互關聯的關係。線條被畫出,鴿子腳被加上,並定義了基數。很容易認為資料庫的骨架僅由表格之間的連結方式決定。然而,這種觀點忽略了真正支撐資料的基礎構建單元:屬性。
屬性是儲存在實體內部的特定資訊片段。它們定義了資料本身的性質,而不僅僅是資料之間的關聯方式。雖然關係決定了網路的結構,但屬性則決定了該網路中資訊的完整性、效能與可用性。忽略屬性設計的細節,可能會導致系統雖能運作,卻在擴展性、資料品質與查詢效率方面舉步維艱。
本指南探討屬性於實體-關係圖(ERD)中所扮演的關鍵角色。我們將超越基本定義,深入探討屬性選擇如何影響資料規範化、儲存優化以及長期可維護性。

🛠️ 資料模型中的屬性定義
屬性是實體的屬性或特徵。在物理資料庫中,這對應於表格內的一個欄位。在概念階段,它是在ER圖中與實體矩形相連的圓形或橢圓形。實體與屬性之間的區別有時會模糊,但簡單的判斷原則是:若資料描述實體且無法獨立存在,則為屬性。
考慮一個顧客實體。姓名、地址與出生日期都是屬性。它們描述顧客,但不像訂單或產品那樣作為獨立的記錄存在。然而,如何儲存這些屬性的決定,正是複雜性開始的地方。
你必須了解的屬性類型
並非所有屬性都同等重要。了解屬性的具體分類,有助於判斷其儲存需求與限制。以下是資料模型過程中常見屬性類型的說明。
| 屬性類型 | 描述 | 範例 |
|---|---|---|
| 簡單屬性 | 原子值;無法再進一步分割。 | 年齡、社會安全號碼 |
| 複合屬性 | 可分割為子部分。 | 地址(街道、城市、郵遞區號) |
| 多值屬性 | 可為單一實體實例儲存多個值。 | 電話號碼、電子郵件位址 |
| 衍生屬性 | 由其他屬性計算得出。 | 年齡(由出生日期計算)、總金額 |
| 關鍵屬性 | 唯一識別實體。 | 顧客編號、訂單編號 |
這些類型中的每一種在邏輯設計階段都需要特別處理。若無法區分簡單屬性與複合屬性,將導致結構僵化,後續難以修改。例如,將完整地址儲存為單一字串,將難以透過城市或郵遞區號進行過濾,除非進行複雜的字串操作。
⚖️ 次要屬性設計不良的隱藏成本
許多團隊將屬性視為在建立關係後才填入的微不足道的細節。這種做法通常會導致顯著的技術債務。當屬性定義不佳時,後果會波及整個系統。
- 資料完整性問題: 如果屬性允許空值卻缺乏明確的業務邏輯,報表就會變得不可靠。如果屬性缺少約束(例如最大長度或有效範圍),資料庫就會接受垃圾資料。
- 查詢效能下降: 在沒有索引的情況下冗餘儲存衍生資料,會導致更新速度變慢。相反地,未對經常查詢的屬性建立索引,會使搜尋操作變得遲緩。
- 規範化違反: 不恰當地拆分或合併屬性,通常會導致資料插入、刪除或更新時出現異常。
- 可擴展性瓶頸: 無限增長的屬性(例如將標籤清單儲存在單一文字欄位中)會阻礙高效能的資料分割與分片策略。
這不僅僅是擁有正確的欄位,更在於擁有正確的約束條件與資料類型。一個varchar欄位用於儲存電話號碼,其效率與準確性都低於能驗證輸入的特定整數或格式化字串類型。
🔍 深入探討:屬性設計模式
為了建立穩健的系統,設計者在定義屬性時應應用特定的設計模式。這些模式能確保資料模型中的一致性與清晰度。
1. 原子性與第一範式
屬性設計的第一條原則是原子性。每個屬性都應僅儲存單一、不可分割的值。避免在一個單元格中儲存多個值。
- 不良做法:一個
skills欄位包含「SQL、Python、Java」。 - 良好做法:一個獨立的關聯表格,連結Employee與Skill.
違反原子性會使查詢變得複雜。若不解析字串,就無法輕易統計有多少員工懂「Python」。保持屬性的原子性,能簡化資料檢索與聚合所需的邏輯。
2. 命名慣例與清晰性
屬性名稱必須具有自明性。模糊不清是可維護性的敵人。避免使用未來開發者可能無法理解的縮寫。屬性應使用單數名詞,以反映其描述的是實體的單一屬性。
- 模糊的:
日期或值. - 明確的:
出生日期或交易金額.
命名的一致性也有助於自動化工具產生文件和程式碼。如果模型在各處都使用 建立時間,則產生的 SQL 查詢也會遵循此模式,從而降低工程團隊的認知負擔。
3. 空值處理
每個屬性都必須有明確的空值規則。在許多系統中,NULL與空字串或零的處理方式不同。是否允許屬性為空,應基於業務邏輯來決定。
- 必要屬性: 如果一個顧客沒有電子郵件地址就無法存在,則該屬性應設定為
NOT NULL. - 選擇性屬性: 如果一個產品可能沒有中間名,則該屬性應允許
NULL.
過度使用NULL 可能導致 SQL 查詢中的三值邏輯錯誤(其中 NULL = NULL 為假)。在設計階段明確處理 NULL 值可避免這些邏輯陷阱。
🧩 屬性與關係:尋找平衡點
經常會就何時停止增加屬性並開始創建新實體展開討論。這就是經典的「屬性對實體」困境。這個決定取決於關係的基數。
如果一個屬性能夠獨立存在,或擁有自己的一組屬性,那麼它很可能應該是一個實體。如果它僅是描述性的且依賴於父實體,則應保持為屬性。
- 情境 A: 一門 車 擁有
顏色屬性。這只是描述性的。它本身沒有獨立的生命。 - 情境 B: 一門 車 擁有一個
所有人。所有人是擁有自己屬性(姓名、地址)的人。這是一種與實體的關係,而非屬性。 - 情境 C: 一門 課程 擁有
主題。如果主題是標準的(數學、科學),它們可以是屬性。如果主題較為複雜(具有描述、難度等級),則應作為實體。
若未能掌握此平衡,將導致資料表過度非規範化,或模型無謂地碎片化。目標是在不引入業務邏輯不需要的複雜性的前提下,捕捉必要的細節。
📉 對規範化的影響
規範化是組織資料以減少冗餘的過程。屬性是在此過程中被移動的主要單元。理解屬性行為對於達到第三範式(3NF)至關重要。
傳遞依賴
當一個非鍵屬性依賴於另一個非鍵屬性時,就會發生傳遞依賴。這是在屬性設計中常見的陷阱。
想像一個訂單資料表,其中包含訂單編號, 顧客編號, 顧客姓名,以及顧客地址.
顧客姓名取決於顧客編號.顧客地址取決於顧客編號.顧客姓名不取決於訂單編號.
在此,顧客地址透過訂單編號顧客編號顧客編號。為了規範化,您必須將顧客屬性移至一個獨立的客戶 表。這可以減少儲存空間,並確保如果客戶搬遷,您只需更新一筆記錄。
函數依賴性
每個屬性都必須明確地依賴於主鍵。如果您無法確定是哪個鍵決定屬性的值,那麼該屬性就不應放在該表中。此檢查對於資料完整性至關重要。
規則: 所有非鍵屬性都必須提供關於鍵、整個鍵,以及僅僅鍵的資訊。
🚫 應避免的常見陷阱
即使經驗豐富的設計師在定義屬性時也可能陷入陷阱。以下是常見錯誤及其預防方法。
1. 儲存衍生資料
為了在查詢時節省運算時間,儲存計算值的誘惑很強。例如,將 總金額 儲存在訂單表中,而不是從 明細項目.
- 風險: 資料不一致。如果項目價格變動,歷史訂單總額就會錯誤,除非您同時更新總金額欄位。
- 解決方案: 僅儲存基本資料。在查詢時或應用程式層計算衍生值。
2. 忽略資料類型
對所有內容都使用通用的字串類型是一種節省時間的快速方法,但會帶來後續問題。以字串儲存的日期無法有效排序或篩選。以字串儲存的數字會阻止數學運算。
- 最佳實務: 選擇符合領域的特定資料類型。依情況使用
DATE,INT,DECIMAL,或BLOB等適當的類型。
3. 忽略字元集
文字屬性需要定義明確的字元集。如果你假設使用 ASCII,但卻收到 UTF-8 輸入,就會遺失特殊字元。這對全球應用程式至關重要。
- 檢查:確保資料庫支援目標使用者所需的排序規則和字元編碼。
🚀 屬性的效能影響
屬性直接影響資料庫引擎存取與儲存資料的方式。屬性的實際實作會影響效能指標。
索引策略
並非所有屬性都應建立索引。索引會增加寫入作業(INSERT、UPDATE、DELETE)的負擔,但能加快讀取作業(SELECT)的速度。
- 高基數:具有許多唯一值的屬性(例如電子郵件)是建立索引的良好候選。
- 低基數:具有少量唯一值的屬性(例如性別或狀態)通常不適合建立索引,除非用於特定的篩選組合中。
儲存效率
與固定長度屬性相比,可變長度屬性可以節省空間,但可能會導致碎片化。了解儲存引擎非常重要。
- 固定長度:讀取速度更快,但如果資料較短則會浪費空間。
- 可變長度:節省空間,由於元資料開銷,讀取速度略慢。
✅ 屬性設計檢查清單
在最終確定你的實體關係圖之前,請逐一檢視此檢查清單,以確保你的屬性具備穩健性。
- ☑️ 每個屬性是否都是原子的(單一欄位中無清單)?
- ☑️ 每個屬性是否都有獨特且具描述性的名稱?
- ☑️ 資料類型是否適合預期的值?
- ☑️ 所有欄位是否都已定義可為空的限制?
- ☑️ 是否已移除衍生屬性,改以計算方式處理?
- ☑️ 是否有任何屬性違反規範化規則?
- ☑️ 儲存空間大小是否針對預期的資料量進行最佳化?
- ☑️ 外鍵是否正確連結至父屬性?
遵循此清單可確保你的資料模型基礎穩固。這能將焦點從「現在是否運作」轉移到「未來多年是否仍能運作」。
🔗 複雜系統中屬性的相互作用
在複雜系統中,屬性通常會跨越多個上下文。考慮一個審計追蹤。您可能需要一個屬性來追蹤是誰更改了記錄以及何時更改。這通常被實現為每個表格上的屬性集合(建立者, 建立時間, 更新者, 更新時間).
雖然這會增加冗餘,但這是為了可追溯性而有意設計的選擇。在這種情況下,屬性不僅僅是數據點;它們是系統的元數據。理解每個屬性的目的,是管理這種複雜性的關鍵。
另一個需要考慮的是國際化。像姓名或地址之類的屬性必須能夠處理不同的格式。單一的屬性結構可能無法滿足全球用戶群的需求。早期設計時就考慮彈性——例如,使用獨立的名稱和姓氏屬性,而不是單一的完整姓名字串——可以大幅減少日後的重構工作量。
🛡️ 安全與隱私考量
屬性通常包含敏感資訊。設計安全性應從識別哪些屬性需要保護開始。
- 個人可識別資訊(PII):姓名、地址和識別碼需要在靜止狀態和傳輸過程中進行加密。
- 存取控制:某些屬性僅應對特定角色可見。ER圖應理想地標註哪些欄位是敏感的,即使執行是在應用程式層級進行。
- 合規性:像GDPR或CCPA之類的法規會影響您儲存某些屬性的時間長度。設計資料結構時,應支援資料保留政策(例如,
到期時間屬性)有助於合規。
在建模階段忽略這些考量,可能會導致日後產生昂貴的安全修補或法律問題。應以與結構性屬性同等的嚴謹態度對待敏感屬性。
📝 重點總結
屬性是您資料庫的實質內容。沒有它們,關係就只是連接空盒子的空線條。一組設計良好的屬性能確保資料的準確性、效率與安全性。
- 專注於原子性:保持資料的細粒度且不可分割。
- 尊重規範化:消除傳遞依賴,以防止異常情況。
- 定義約束:使用資料類型和可空性來強制執行業務規則。
- 考慮效能:明智地建立索引並謹慎選擇儲存類型。
- 規劃安全性:盡早識別敏感資料。
透過投入時間於屬性設計的細節,您將建立一個能抵禦變更且運作高效的資料模型。ER圖的威力不僅在於其連結,更在於它所捕捉的細節精確度。










