大表刪除/更新後索引碎片嚴重,需針對特定表、特定大小以上的索引批量生成 `REBUILD WITH (DATA_COMPRESSION = PAGE)` 腳本。
DECLARE @TableName SYSNAME = 'tblOrders'; -- 目標表
DECLARE @MinIndexSizeMB INT = 0; -- 最小索引大小 (MB),0 表示全部
SELECT
'ALTER INDEX ' + QUOTENAME(i.name) + ' ON ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.OBJECT_ID)) + '.' + QUOTENAME(OBJECT_NAME(i.OBJECT_ID)) +
' REBUILD WITH (DATA_COMPRESSION = PAGE, ONLINE = ON, MAXDOP = 4);' AS RebuildScript
FROM sys.indexes i
JOIN sys.partitions p ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id
JOIN sys.allocation_units a ON a.container_id = p.partition_id
WHERE i.OBJECT_ID = OBJECT_ID(@TableName)
AND i.index_id > 0 -- 排除堆
AND i.type_desc <> 'HEAP'
GROUP BY i.OBJECT_ID, i.index_id, i.name
HAVING (8.0 * SUM(a.used_pages) / 1024) > @MinIndexSizeMB
ORDER BY (8.0 * SUM(a.used_pages) / 1024) DESC;
ALTER INDEX [IX_tblOrders_CustomerID] ON [dbo].[tblOrders] REBUILD WITH (DATA_COMPRESSION = PAGE, ONLINE = ON, MAXDOP = 4);
ALTER INDEX [PK_tblOrders] ON [dbo].[tblOrders] REBUILD WITH (DATA_COMPRESSION = PAGE, ONLINE = ON, MAXDOP = 4);
| 選項 | 作用 | 建議 |
|---|---|---|
| DATA_COMPRESSION = PAGE | 頁級壓縮,節省 40-60% 空間,CPU 微增 | OLAP/歸檔表強推,OLTP 評估 CPU |
| ONLINE = ON | 企業版專有,重建過程不阻塞讀寫 | 生產環境必開 |
| MAXDOP = 4 | 限制並行度,避免佔滿 CPU | 根據核心數調整,通常 2-8 |
| SORT_IN_TEMPDB = ON | 中間排序結果寫 tempdb,減少用戶庫日志 | 大索引建議開啟 |
SELECT
OBJECT_SCHEMA_NAME(ips.OBJECT_ID) + '.' + OBJECT_NAME(ips.OBJECT_ID) AS TableName,
i.name AS IndexName,
ips.index_type_desc,
ips.avg_fragmentation_in_percent,
ips.page_count * 8.0 / 1024 AS SizeMB,
CASE WHEN ips.avg_fragmentation_in_percent > 30 THEN 'REBUILD'
WHEN ips.avg_fragmentation_in_percent > 5 THEN 'REORGANIZE'
ELSE 'OK' END AS Action
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON i.OBJECT_ID = ips.OBJECT_ID AND i.index_id = ips.index_id
WHERE ips.index_id > 0 AND ips.page_count > 1000
ORDER BY ips.avg_fragmentation_in_percent DESC;