iT邦幫忙

5

想請教如何定義資料庫的Primary Key

  • 分享至 

  • xImage

大家好
最近需要新增一個資料表可以儲存使用者填寫的資料
至於Primary Key我原本是想用使用者帳號
但是看到有文章說是比較推薦用使用者那張表的流水號,理由是效能比較好一點
缺點就是查詢時需要JOIN使用者表
這讓我有點猶豫,所以想問問大家是否有比較推薦的做法是什麼?
感激不盡了!

看更多先前的討論...收起先前的討論...
jim_xxl iT邦新手 5 級 ‧ 2025-09-16 11:02:42 檢舉
先說哪一個資料庫可能比較好回答
雷N iT邦研究生 1 級 ‧ 2025-09-16 11:37:09 檢舉
你有哪些行為要存取這表
雷N iT邦研究生 1 級 ‧ 2025-09-16 11:38:35 檢舉
使用者那張表的流水號,理由是效能比較好一點
連續號的話,這mysql在新增資料時確實是這樣.

新增一個資料表可以儲存使用者填寫的資料? 能否說明白需求跟這些實體表之間的關聯?
Jasper iT邦新手 5 級 ‧ 2025-09-16 12:53:24 檢舉
等等!你所說的缺點跟 primary key 之間有什麼關聯性嗎?
看資料庫規模,看系統規模

我公司的
ERP 資料庫 人員資料表primary key 是員工編號, 資料庫系統是MS SQL
MES 資料庫人員資料表 primary key 是流水號, 資料庫系統是Oracle
pizza0223 iT邦新手 5 級 ‧ 2025-09-16 14:03:50 檢舉
不曉得你資料表筆數會有多少
一般來說的確是使用流水號會比較好一點
因為資料長度會比較短搜尋比較快
但還是要看你的用途而定

不過,為什麼使用者資料表的流水號跟帳號欄位不能共存?
這沒有一定要分成兩個表作查詢
muscat iT邦新手 4 級 ‧ 2025-09-17 01:12:35 檢舉
謝謝大家,在此回答一下疑問
1.資料庫是SQL SERVER
2.主要是讓使用者登入後填寫表單,然後填的資料內容都存在這張表
3.使用者流水號是int,帳號是NVARCHAR(50),用int的話似乎資料庫在JOIN/索引效能都會比較好
4.表單資料我的確是沒有想到把使用者的流水號跟帳號都一起存,只是單純想要用一個欄位當PK知道是哪位使用者填寫的資料而已
5.有部分我忘了說,使用者大約1.5萬人,表單每人每年都需要上來填,所以有第二個PK是年度,資料增長幅度可能有點大,有點擔心幾年後的效能
雷N iT邦研究生 1 級 ‧ 2025-09-17 09:08:35 檢舉
那聽起來就使用者的流水號跟年度(整數) 作為pk 的兩個欄位就好了。我好奇1.5萬人,100年後也才150萬筆左右,這樣對資料庫其實都還是小case, 但你擔心效能是指什麼?有先測量過取得基線或有期望達成的效能目標嗎?
資料"表"的Primary Key的選擇 是找此表欄位中具備獨立性(不會有重複值)的欄位,像員工的ID,不然就會建流水號欄位,供您參考!!
雷N iT邦研究生 1 級 ‧ 2025-09-17 10:39:52 檢舉
"表單每人每年都需要上來填" 所以表單這件事情本身有綁活動嗎?
還是就單純的user+年,等於這張表有點像每年員工的自評表這樣?
反正員工每年就上來填寫自評,你要存取這件事情?
雷N iT邦研究生 1 級 ‧ 2025-09-17 10:41:17 檢舉
如果就像我說的那樣的話,那其實你等於存取就是拿使用者id, 跟今年的年度來撈出這表的自評內容或者用left join,快速找出哪些員工還沒填寫自評.
1️⃣ 兩種設計方式
設計方式
說明
優點
缺點
用使用者帳號當 Primary Key(自然鍵)
直接用 username 或 email 當主鍵
‧ 少一個欄位,不用 JOIN 就能取得帳號‧ 查詢語意直覺
‧ username 變動會牽連到外鍵表 (很痛)‧ PK 長度較長 → index、join 效能差‧ 不適合複合情境(可能有多筆相同帳號對應不同記錄)
用使用者表的流水號/ID 當 Primary Key(代理鍵)
用 user_id (INT/BIGINT) 做 PK,username 放在 users 表
‧ Index 短小、查詢 join 效能好‧ 不受 username 改名影響‧ 擴充性佳
‧ 查詢需要 JOIN users 才拿到 username
2️⃣ 業界實務建議
• 幾乎所有大型系統(電商、社交、ERP)都傾向用「代理鍵(流水號/UUID)」作為 PK。
• username、email 之類資料應該放在「業務層邏輯」欄位,並加上 唯一索引(UNIQUE INDEX) 去保證不重複,而不是 PK。
• 因為 username 可能會改名(例如用戶申請更改帳號、改綽號、改綁定信箱),用自然鍵做 PK 會很麻煩。



3️⃣ JOIN 的顧慮
• JOIN 的確多了一個步驟,但用整數型 PK JOIN 效能幾乎不會差,反而比用文字 PK 好很多。
• 如果查詢常常需要帳號名稱,可以在資料表直接存一份冗餘欄位(例如 username_cache),或者在查詢層做 VIEW 或 MATERIALIZED VIEW 來減少 JOIN。



4️⃣ 建議做法(綜合)
• 在使用者主表:
• user_id (INT/BIGINT, Primary Key, Auto Increment or UUID)
• username (VARCHAR, UNIQUE INDEX)
• 在你的新資料表:
• id (Primary Key, Auto Increment)
• user_id (Foreign Key → users.user_id)
• 其他資料欄位
• 如果需要 username 很常用:
• 在查詢時 JOIN users 表
• 或在新表多加一個 username 作快取,定期同步



5️⃣ 簡短結論

✅ 用「使用者表的流水號/ID」做 Foreign Key + Primary Key。
❌ 不建議用 username 當 PK。
💡 需要顯示 username 再 JOIN 或做快取。
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
sam0407
iT邦大師 1 級 ‧ 2025-09-17 09:29:06

先說觀念:

  1. 在所有的資料庫系統中,一個資料表只會有一個PK,而PK可以是一個以上的欄位所組成,在一個資料表中,PK必須是唯一值,不可出現重覆的資料。
  2. 在SQL Server中PK又叫叢集索引(Clustered Index),實際資料存到硬碟上是依叢集索引的順序來儲存的,所以在理論上以PK作條件來查詢資料表後,讀取的速度會比較快(循序讀取會比隨機讀取快)

解析您的案例:

  1. 應該已有使用者帳號的資料表了吧?使用者帳號應該目前沒有重覆的吧?直接將使用者帳號設為PK,就算新增帳號的程式沒在作控管,以後也不可能重覆,因為PK的限制就會擋下了。
  2. 再來就是您要新增的資料表,這個資料表一個帳號每年度只會有一筆資料,所以PK可設為:年度+使用者帳號。這個資料表其實不設PK也可以,分別設"年度"及"使用者帳號"兩個獨立的Index,這樣無論是您要查某個使用者各年度的資料,或是要查某個年度所有所使用者的資料都可以用上對應的索引

我要發表回答

立即登入回答