SQL Server通過整理索引碎片和重建索引提高速度


本文章轉載:http://database.51cto.com/art/201108/282408.htm

SQL Server數據庫中,當索引碎片太多時,就會拖慢數據庫查詢的速度。這時我們可以通過整理索引碎片和重建索引來解決,本文我們主要就介紹了這部分內容,希望能夠對您有所幫助。

 

SQL Server數據庫操作中,當數據庫中的記錄比較多的時候,我們可以通過索引來實現查詢。但是當索引碎片太多的時候,就會很嚴重地影響到查詢的速度。這時候我們可以采取兩種方法來解決:一種時整理索引碎片,另一種是重建索引

 

索引是數據庫引擎中針對表(有時候也針對視圖)建立的特別數據結構,用來幫助查找和整理數據。索引的重要性體現在能夠使數據庫引擎快速返回查詢
結果。當對索引所在的基礎數據表進行修改時(包括插入、刪除和更新等操作),會導致索引碎片的產生。當索引的邏輯排序和基礎表或視圖的物理排序不匹配時,
就會產生索引碎片。隨着索引碎片的不斷增多,查詢響應時間就會變慢,查詢性能也會下降。在SQL Server
2005中,要解決這個問題,要么重新組織索引要么重新生成索引。

 

索引碎片的產生:http://blog.sina.com.cn/s/blog_792e033201013fkj.html

索引能夠加快對表的訪問速度,然而任何事物都有兩面性,索引在帶給我們便利的同時也會占用額外的磁盤空間,並且我們在對表進行增刪改的操作時也要消耗額外的時間來更新索引。而在我們對包含索引的表進行增刪改時,也會造成索引碎片,久而久之,索引碎片程度越來越高,反而會降低我們對表的訪問速度。因此作為數據庫管理員,要定期維護索引,修復索引碎片。

 

 

怎樣確定索引是否有碎片? http://blog.tianya.cn/blogger/post_read.asp?BlogID=2587659&PostID=24488142
  
  SQLServer提供了一個數據庫命令――DBCC SHOWCONTIG――來確定一個指定的表或索引是否有碎片。
  DBCC SHOWCONTIG
  數據庫平台命令,用來顯示指定的表的數據和索引的碎片信息。
  
  DBCC SHOWCONTIG 權限默認授予 sysadmin固定服務器角色或 db_owner 和 db_ddladmin固定數據庫角色的成員以及表的所有者且不可轉讓。
  語法(SQLServer2000)
  
  DBCC SHOWCONTIG
  [ ( { table_name | table_id| view_name | view_id }
  [ , index_name | index_id ]
  )
  ]
  [ WITH { ALL_INDEXES
  | FAST [ , ALL_INDEXES ]
  | TABLERESULTS [ , { ALL_INDEXES } ]
  [ , { FAST | ALL_LEVELS } ]
  }
  ]
  
  語法(SQLServer7.0)
  
  DBCC SHOWCONTIG
  [ ( table_id [,index_id ]
  )
  ]

 

那么SQL Server如何的定期清理索引碎片呢?可以做個Job作業計划,定期的執行。

--更新統計信息
EXEC sp_updatestats



---索引優化
DECLARE @tableName NVARCHAR(50) ,
    @indexName NVARCHAR(50) ,
    @fragmentPercent NVARCHAR(20) ,
    @sql NVARCHAR(200)= ''
DECLARE indexFragment_cursor CURSOR
FOR
    SELECT  o.name AS tableName ,
            ix.name AS indexName ,
            avg_fragmentation_in_percent AS fragmentPercent--,
    --dip.fragment_count,
    --dip.avg_fragment_size_in_pages
    FROM    sys.dm_db_index_physical_stats(DB_ID() ,NULL ,NULL ,NULL ,NULL) dip
            INNER JOIN sys.indexes ix ON ix.index_id = dip.index_id
                                         AND ix.object_id = dip.object_id
            INNER JOIN sys.objects o ON ix.object_id = o.object_id
    WHERE   dip.index_id > 0
            AND avg_fragmentation_in_percent > 5
    ORDER BY avg_fragmentation_in_percent DESC

--打開游標
OPEN indexFragment_cursor 
FETCH NEXT 
    FROM indexFragment_cursor 
    INTO @tableName ,@indexName ,@fragmentPercent
WHILE @@FETCH_STATUS = 0 
    BEGIN
    --print @tableName+'----'+@indexName++'----'+@fragmentPercent
        SET @sql = 'ALTER INDEX ' + QUOTENAME(@indexName) + ' on '
            + QUOTENAME(@tableName)
            + CASE WHEN @fragmentPercent <= '30' THEN ' REORGANIZE;'
                   WHEN @fragmentPercent > '30' THEN ' REBUILD;'
              END
    --print @sql
        EXEC(@sql)
    --移到下一行記錄
        FETCH NEXT 
        FROM indexFragment_cursor 
        INTO @tableName ,@indexName ,@fragmentPercent
    END

--關閉,釋放游標
CLOSE indexFragment_cursor
DEALLOCATE indexFragment_cursor



GO

  SQL 2008 R2索引的重建:http://www.2cto.com/database/201204/128616.html

項目升級數據庫由SQL2000升級到2008R2,今天對數據庫表進行碎片掃描,發現有些表碎片較大,於是決定重建索引,聯機幫助是最好的老師,將相關腳本摘錄備后查。

參考sys.dm_db_index_physical_stats

檢查索引碎片情況

 

SELECT

    OBJECT_NAME(object_id) as objectname,

    object_id AS objectid,  www.2cto.com  

    index_id AS indexid,

    partition_number AS partitionnum,

    avg_fragmentation_in_percent AS fra

FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')

WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;

使用腳本中的 sys.dm_db_index_physical_stats 重新生成或重新組織索引 (來源於聯機幫助)

 

SET NOCOUNT ON;

DECLARE @objectid int;

DECLARE @indexid int;

DECLARE @partitioncount bigint;

DECLARE @schemaname nvarchar(130); 

DECLARE @objectname nvarchar(130); 

DECLARE @indexname nvarchar(130); 

DECLARE @partitionnum bigint;

DECLARE @partitions bigint;

DECLARE @frag float;  www.2cto.com  

DECLARE @command nvarchar(4000); 

-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function 

-- and convert object and index IDs to names.

SELECT

    object_id AS objectid,

    index_id AS indexid,

    partition_number AS partitionnum,

    avg_fragmentation_in_percent AS frag

INTO #work_to_do

FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')

WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;

 

-- Declare the cursor for the list of partitions to be processed.

DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;

 

-- Open the cursor.

OPEN partitions;

 

-- Loop through the partitions.

WHILE (1=1)

    BEGIN;

        FETCH NEXT

           FROM partitions

           INTO @objectid, @indexid, @partitionnum, @frag;

        IF @@FETCH_STATUS < 0 BREAK;

        SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)

        FROM sys.objects AS o  

        JOIN sys.schemas as s ON s.schema_id = o.schema_id

        WHERE o.object_id = @objectid;

        SELECT @indexname = QUOTENAME(name)

        FROM sys.indexes

        WHERE  object_id = @objectid AND index_id = @indexid;

        SELECT @partitioncount = count (*)

        FROM sys.partitions

        WHERE object_id = @objectid AND index_id = @indexid;

 

-- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.

        IF @frag < 30.0

            SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';

        IF @frag >= 30.0

            SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';

        IF @partitioncount > 1

            SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));  www.2cto.com  

        EXEC (@command);

        PRINT N'Executed: ' + @command;

    END;

 

-- Close and deallocate the cursor.

CLOSE partitions;

DEALLOCATE partitions;

 

-- Drop the temporary table.

DROP TABLE #work_to_do;

GO

  

 UPDATE STATISTICS更新統計信息來提高查詢效率. 

該命令在一張表或者索引了的視圖上更新查詢優化統計數字信息. 默認情況下, 查詢優化器已經更新了必要的用來提高查詢計划的統計信息; 在某些情況下, 你可以通過使用UPDATE STATISTICS 命令或者存儲過程sp_updatestats 來比默認更頻繁地更新統計信息來提高查詢效率. 

 

更新統計信息能確保查詢能以最新的統計信息來編譯. 然而, 更新統計信息會引起查詢的重新編譯. 我們建議不要過於頻繁地更新統計信息, 因為這里有一個在提高查詢計划和用來重新編譯查詢的權衡. 具體的權衡要看你的應用程序而定.


免責聲明!

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



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