Tôi sử dụng kịch bản này. Xin lưu ý rằng tôi sẽ khuyên bạn đọc về dmv mà tôi đang sử dụng ở đây, chúng là một viên ngọc ẩn trong SQL2005 +.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
CREATE TABLE #FragmentedIndexes
(
DatabaseName SYSNAME
, SchemaName SYSNAME
, TableName SYSNAME
, IndexName SYSNAME
, [Fragmentation%] FLOAT
)
INSERT INTO #FragmentedIndexes
SELECT
DB_NAME(DB_ID()) AS DatabaseName
, ss.name AS SchemaName
, OBJECT_NAME (s.object_id) AS TableName
, i.name AS IndexName
, s.avg_fragmentation_in_percent AS [Fragmentation%]
FROM sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'SAMPLED') s
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas ss ON ss.[schema_id] = o.[schema_id]
WHERE s.database_id = DB_ID()
AND i.index_id != 0
AND s.record_count > 0
AND o.is_ms_shipped = 0
DECLARE @RebuildIndexesSQL NVARCHAR(MAX)
SET @RebuildIndexesSQL = ''
SELECT
@RebuildIndexesSQL = @RebuildIndexesSQL +
CASE
WHEN [Fragmentation%] > 30
THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
+ QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName) + ' REBUILD;'
WHEN [Fragmentation%] > 10
THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
+ QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName) + ' REORGANIZE;'
END
FROM #FragmentedIndexes
WHERE [Fragmentation%] > 10
DECLARE @StartOffset INT
DECLARE @Length INT
SET @StartOffset = 0
SET @Length = 4000
WHILE (@StartOffset < LEN(@RebuildIndexesSQL))
BEGIN
PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
SET @StartOffset = @StartOffset + @Length
END
PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
EXECUTE sp_executesql @RebuildIndexesSQL
DROP TABLE #FragmentedIndexes
Cũng nên nhớ rằng tập lệnh này có thể chạy một lúc và chặn quyền truy cập vào các bảng của bạn. Trừ khi bạn có phiên bản Doanh nghiệp, SQL có thể KHÓA bảng khi xây dựng lại chỉ mục. Thao tác này sẽ chặn tất cả các truy vấn tới bảng đó bằng cách sử dụng chỉ mục cho đến khi quá trình chống phân mảnh chỉ mục hoàn tất. Vì vậy, không nên chạy xây dựng lại chỉ mục trong giờ hoạt động chỉ trong thời gian bảo trì. Nếu bạn đang chạy phiên bản doanh nghiệp, bạn có thể sử dụng tùy chọn ONLINE =ON để phân mảnh các chỉ mục trực tuyến. Điều này sẽ sử dụng nhiều không gian hơn nhưng bảng của bạn sẽ không bị chặn / khóa trong quá trình chống phân mảnh.
Hãy hét lên nếu bạn cần thêm thông tin.
CẬP NHẬT:
Nếu bạn đang chạy truy vấn này trên một cơ sở dữ liệu nhỏ hơn, bạn có thể sử dụng tham số 'DETAILED' trong lệnh gọi tới sys.dm_db_index_physical_stats. Đây có lẽ là một kiểm tra chi tiết hơn về các chỉ số. Thảo luận trong các nhận xét cũng sẽ chỉ ra rằng trên các bảng lớn hơn nhiều, có lẽ nên thực hiện quét MẪU vì điều này sẽ giúp giảm thời gian cần thiết để quét chỉ mục.