為什麼一個表的數據空間可能會佔用原始數據大小的 4 倍?
我有一個包含 4.9 億行和 55 GB 表空間的表,因此每行大約 167 個字節。該表包含三列: a
VARCHAR(100)
、 aDATETIME2(0)
和 aSMALLINT
。欄位中文本的平均長度VARCHAR
約為 21.5,因此原始數據應約為每行 32 個字節: 22+2 用於VARCHAR
, 6 用於DATETIME2
, 2 用於 16 位整數。請注意,上面的空間只是數據,而不是索引。我正在使用屬性下報告的值 | 儲存 | 一般 | 數據空間。
當然必須有一些成本,但是每行 135 個字節似乎很多,尤其是對於一個大表。為什麼會這樣?有沒有其他人見過類似的乘數?哪些因素會影響所需的額外空間量?
為了比較,我嘗試創建一個包含兩個
INT
欄位和 1 M 行的表。所需的數據空間為 16.4 MB:每行 17 個字節,而原始數據為 8 個字節。另一個測試表使用與真實表相同的文本填充了一個INT
和一個,每行使用 39 個字節(44 K 行),我預計會多出 28 個字節。VARCHAR(100)
所以生產表的成本要大得多。這是因為它更大嗎?我希望索引大小大約為 N * log(N),但我不明白為什麼實際數據所需的空間是非線性的。
提前感謝您的任何指點!
編輯:
列出的所有欄位都是
NOT NULL
.VARCHAR
真實表在欄位和DATETIME2
欄位上按該順序具有聚集的 PK 。對於這兩個測試,第一個INT
是(集群)PK。如果重要:該表是 ping 結果的記錄。這些欄位是 URL、ping 日期/時間和延遲(以毫秒為單位)。數據會不斷地添加,並且永遠不會更新,但會定期刪除數據以將其減少到每個 URL 每小時僅幾條記錄。
編輯:
這裡的一個非常有趣的答案表明,對於具有大量讀寫的索引,重建可能沒有好處。在我的情況下,消耗的空間是一個問題,但如果寫入性能更重要,那麼使用鬆弛的索引可能會更好。
在對原始問題的評論中進行了討論後,在這種情況下,失去的空間是由選擇聚集鍵引起的,這導致了大量的碎片。
在這些情況下,總是值得通過 sys.dm_db_index_physical_stats 檢查碎片狀態。
編輯:在評論中更新
平均頁面密度(在重建聚集索引之前)為 24%,與原始問題完全吻合。這些頁面只有 1/4 滿,所以總大小是原始數據大小的 4 倍。