SQL Server 索引的自動維護 <第十三篇>


  在有大量事務的數據庫中,表和索引隨着時間的推移而碎片化。因此,為了增進性能,應該定期檢查表和索引的碎片,並對具有大量碎片的進行整理。

  1、確定當前數據庫中所有需要分析碎片的表。

  2、確定所有表和索引的碎片。

  3、考慮一下因素以確定需要進行碎片整理的表和索引。

  •   高的碎片水平-avg_fragmentation_in_percent大於20%;
  •   不是非常小的表或索引-也就是page_count大於8的;

  4、整理具有大量碎片的表和索引;

  這里給出一個樣板SQL存儲過程,它執行以下操作;

  •   遍歷系統上的所有數據庫並確認符合碎片條件的每個數據庫中表上的索引,並將它們保存到一個臨時表中;
  •   根據碎片水平,重新整理碎片較少的索引並重建碎片很多的索引。
CREATE PROCEDURE IndexDefrag
AS

DECLARE @DBName NVARCHAR(255)
    ,@TableName NVARCHAR(255)
    ,@SchemaName NVARCHAR(255)
    ,@IndexName NVARCHAR(255)
    ,@PctFrag DECIMAL

DECLARE @Defrag NVARCHAR(MAX)

IF EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'#Frag'))
    DROP TABLE #Frag

CREATE TABLE #Frag
(DBName NVARCHAR(255)
,TableName NVARCHAR(255)
,SchemaName NVARCHAR(255)
,IndexName NVARCHAR(255)
,AvgFragment DECIMAL)

EXEC sp_msforeachdb 'INSERT INTO #Frag (
    DBName,
    TableName,
    SchemaName,
    IndexName,
    AvgFragment
) SELECT  ''?'' AS DBName
       ,t.Name AS TableName
       ,sc.Name AS SchemaName
       ,i.name AS IndexName
       ,s.avg_fragmentation_in_percent 
FROM    ?.sys.dm_db_index_physical_stats(DB_ID(''?''), NULL, NULL,
                                       NULL, ''Sampled'') AS s
        JOIN ?.sys.indexes i
        ON s.Object_Id = i.Object_id
           AND s.Index_id = i.Index_id
        JOIN ?.sys.tables t
        ON i.Object_id = t.Object_Id
        JOIN ?.sys.schemas sc
        ON t.schema_id = sc.SCHEMA_ID
WHERE s.avg_fragmentation_in_percent > 20
AND t.TYPE = ''U''
AND s.page_count > 8
ORDER BY TableName,IndexName'

DECLARE cList CURSOR
FOR SELECT * FROM #Frag

OPEN cList
FETCH NEXT FROM cList
INTO @DBName, @TableName,@SchemaName,@IndexName,@PctFrag
WHILE @@FETCH_STATUS = 0
BEGIN
    IF @PctFrag BETWEEN 20.0 AND 40.0
    BEGIN
        SET @Defrag = N'ALTER INDEX ' + @IndexName + ' ON ' + @DBName + '.' + @SchemaName + '.' + @TableName + ' REORGANIZE'
        EXEC sp_executesql @Defrag        
        PRINT 'Reorganize index: ' + @DBName + '.' + @SchemaName + '.' + @TableName +'.' + @IndexName
    END
    ELSE IF @PctFrag > 40.0
    BEGIN
        SET @Defrag = N'ALTER INDEX ' + @IndexName + ' ON ' + @DBName + '.' + @SchemaName + '.' + @TableName + ' REBUILD'
        EXEC sp_executesql @Defrag
        PRINT 'Rebuild index: '+ @DBName + '.' + @SchemaName + '.' + @TableName +'.' + @IndexName
    END
        
    FETCH NEXT FROM cList
    INTO @DBName, @TableName,@SchemaName,@IndexName,@PctFrag

END
CLOSE cList
DEALLOCATE cList

DROP TABLE #Frag

  為了自動化碎片分析過程,可以從SQL Server企業管理器中用以下簡單的步驟創建一個SQL Server任務。

  1、開啟SQL Server代理;

  

  2、打開Management Studio,右鍵單擊,選擇新建=》任務;

  

  3、在新建任務對話框的“常規”頁面中,輸入任務名稱和其他細節:

  

  4、在新建任務對話框的“步驟”頁面中,單擊“新建”並輸入用戶數據庫的SQL命令。

  

  5、在新建任務步驟對話框“高級”頁面上,輸入報告碎片分析結果的輸出文件名稱:

  

  6、單擊“確定”按鈕,返回新建作業對話框;

  7、在新建任務對話框“計划”頁面,單擊“新建計划”,並輸入運行SQL Server任務的合適計划:

  

  安排這個存儲過程在非高峰執行。為了確定數據庫的數據庫模式,記錄整天的SQL Server:SQL Statistics\Batch Requests/sec性能計數器,它將展示數據庫負載的波動。

  8、單擊“確定”按鈕,返回新建任務對話框。

  9、輸入所有信息后,單擊新建任務對話框中的“確定”按鈕創建SQL Server任務。創建計划在一個固定時間間隔(每周)運行sp_indexDefrag存儲過程的SQL Server任務。

  10、確保SQL Server代理運行,這樣SQL Server任務將自動根據設置的計划運行。

  這個SQL任務將在每個星期天的凌晨1點分析每個數據庫並且進行碎片整理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM