與高碎片堆進行性能比較的注意事項?
我計劃對同一張表的不同結構進行一些性能比較。我要調查的表是一個有 ~ 1Mio 行和 123 列的堆。
設置: 我已將表從生產系統複製到測試系統。這是一個堆表,我想檢查選項以改進它。然後我創建了該表數據的 3 個新副本。
副本1:
- 主鍵上的聚集索引(唯一標識符)
- 相同的非聚集索引和外鍵
副本2:
- 現有 IDENTITY 列上的聚集索引
- 相同的非聚集索引和外鍵
副本3:
- 另一個 uniqueidentifier 和 int 列上的聚集索引,經常用於過濾行列表
- 相同的非聚集索引和外鍵
我從生產環境中收集了幾個典型且經常使用的範例 INSERT、UPDATE 和 SELECT 查詢。我的計劃是針對所有這四個表多次執行這些表,並比較總 IO 統計資訊和總 cpu 時間統計資訊以及執行計劃詳細資訊,以希望得出一個有價值的結果,告訴我哪個表在正常查詢中表現最好應用。
由於三個表副本是全新的,所以沒有碎片到位。為了公平比較,我還重新建構了原始表的所有索引。
我不確定這個表的“堆索引”的碎片,它是~60%。我想知道我是否必須先處理這個問題,還是讓它保持原樣,因為它也將在生產中到位,即使我修復了它,它也會回來並可能影響查詢性能?
除了對上述問題的回答外,我還感謝任何有用的評論,以及要考慮哪些內容才能獲得這項工作的最佳結果。特別是關於數據記憶體。不確定我是否應該總是在查詢之前清除它,或者更好地執行一次查詢以在取樣之前填充它?
由於三個表副本是全新的,所以沒有碎片到位。為了公平比較,我還重新建構了原始表的所有索引。
更現實的測試是嘗試重新創建從一開始就存在於每個設計中的表所導致的碎片。通過這種方式,您可以比較設計的結果,因為它們會關注現實世界的使用,而不是重新建構之後。
如果您的應用程序為該數據保留了完整的審計跟踪,那麼您也許可以通過回复該審計來重建每個副本。否則,您可能需要編寫一些啟發式方法(例如,如果數據包含創建日期或上次修改日期,則按該順序將行插入每個副本)。
這樣做時要注意的一件事是單獨執行每個插入而不是塊複製 - 當您一次插入或更新多行時,它足夠明亮,可以將索引更新捆綁在一起,以減少它不能對個人進行的頁面拆分實際應用程序訪問導致的插入。下面將說明這一點(使用分配的空間量作為由 UUID 排序的隨機性引起的頁面拆分導致的可用頁面空間碎片的指示):
SET NOCOUNT ON CREATE DATABASE TestFragUUID GO USE TestFragUUID CREATE TABLE IndividualInserts (ID UNIQUEIDENTIFIER PRIMARY KEY CLUSTERED, AnotherID UNIQUEIDENTIFIER UNIQUE) CREATE TABLE SingleLargeInsert (ID UNIQUEIDENTIFIER PRIMARY KEY CLUSTERED, AnotherID UNIQUEIDENTIFIER UNIQUE) GO INSERT IndividualInserts SELECT NEWID(), NEWID() GO 100000 WITH CTen AS (SELECT TOP 10 name FROM sys.objects) INSERT SingleLargeInsert SELECT NEWID(), NEWID() FROM CTen unit CROSS JOIN cTen ten CROSS JOIN cTen hun CROSS JOIN cTen tho CROSS JOIN cTen tth GO EXEC sp_spaceUsed 'IndividualInserts' EXEC sp_spaceUsed 'SingleLargeInsert' GO USE master DROP DATABASE TestFragUUID