VARCHAR 主鍵 - MySQL
目前,我有一個
categories
有 2 列的表 -category VARCHAR(50) NOT NULL PRIMARY KEY
和parent VARCHAR(50)
. 該parent
列是該列的外鍵 (FK)category
。這似乎是最明顯的方法。但是,警鐘在我腦海中響起,因為我正在使用
VARCHAR
列作為主鍵,這可能會在查詢表時減慢操作速度。我可以引入第三列
cat_id INT AUTO_INCREMENT
並將其設置為 PK,但它會引入一個沒有意義的新列。除了哪一個會更快,還有什麼其他的考慮?
注意,我預測最多會有 1000 個類別左右,所以行數不是很高。但是,
categories
PK 列將成為其他表中許多外鍵的參考列。我也應該使用(唯一)使用者名作為 PK 嗎?
VARCHAR
列作為主鍵不是一個好的選擇,因為通常我們在同一列上創建集群索引。由於預期的高碎片率,VARCHAR 列上的集群索引是一個糟糕的選擇。每個新插入的鍵值都會嘗試在現有鍵之間的某個位置找到它的位置,通常會導致頁面拆分和高索引碎片。結果導致性能不佳和額外的索引重建/重組成本。
其次,
varchar
與偽鍵列相比,使用鍵列作為外鍵將佔用額外的空間auto-incremented
。但
自動遞增列上的聚集索引可能會創建“熱點”。仔細閱讀這篇文章“避免基於遞增鍵創建聚集索引”是 SQL Server 2000 天的神話嗎?
儘管熱點可能是一個問題,但是當許多使用者嘗試插入值時,但在您的情況下,與 varchar 相比,我仍然希望使用自動遞增列。
是的,我會添加一個代理 4 字節整數鍵。您目前的兩列是 100 字節,然後可以通過添加新的標識列將其減少到 58 字節。如果您確定永遠不會超過 65,535 個類別,您甚至可以將代理鍵設為 2 字節 smallint(以防萬一,保留為 INT 可能仍然是個好主意)。
對於 1,000 行的表來說,節省的空間並不大,但它是 cat_id 添加到其他表的地方,您可以節省大量空間(每個 FK 中 4 個字節而不是 50 個)。您可能還希望索引這些外鍵,因此在所有非聚集索引中節省的空間也會更大。
此外,您的聚集索引現在是順序的,以避免在添加新類別時出現碎片(頁面拆分)
表結構:-
create table dbo.Cateogory ( CateogoryID int not null identity(1,1) constraint pkCateogory primary key clustered, Cateogory varchar(50) not null constraint ukCateogory unique nonclustered, ParentCateogoryID int null constraint fkCateogory references dbo.Cateogory(CateogoryID) )
您還可以根據您的要求在生產中添加索引選項(填充因子等)。