Sql-Server-2008

為什麼一個表的數據空間可能會佔用原始數據大小的 4 倍?

  • May 13, 2020

我有一個包含 4.9 億行和 55 GB 表空間的表,因此每行大約 167 個字節。該表包含三列: a VARCHAR(100)、 aDATETIME2(0)和 a SMALLINT。欄位中文本的平均長度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 倍。

引用自:https://dba.stackexchange.com/questions/5455