2009-07-06 8 views
12

Kann jemand das Skript zum Neuerstellen und erneuten Indexieren des fragmentierten Index bereitstellen, wenn 'avg_fragmentation_in_percent' bestimmte Grenzen überschreitet (besser, wenn der Cursor nicht verwendet wird)?Skript zum Neuerstellen und Reindexieren des fragmentierten Index?

+1

Warum nicht? Jeder kann wählen, um eine Frage zu stellen, die er eine Wiki-Frage stellt. Es vermeidet, Rep-Punkte zu verlieren. –

+0

@Savitha: welcher Teil ist das Problem? Ich bin mir nicht sofort sicher, wie Sie die Operation mit einem Cursor durchführen würden. Suchen Sie ein Skript, um den Prozentsatz zu erkennen und dann neu zu erstellen? Haben Sie das Handbuch für Optionen überprüft? Was sind die verfügbaren Aussagen? Müssen Sie die Indexdetails ermitteln? Gibt es eine ALTER INDEX-Anweisung? –

+0

@ Jonathan Leffler, aber das ist eine gute legitime Frage mit wenig Risiko, Stimmen zu bekommen. Weniger Leute sehen Wikis und/oder wollen für Nullpunkte antworten. –

Antwort

18

Verwendung neu zu erstellen:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REBUILD 

oder Verwendung reorganisieren:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REORGANIZE 

reorganisieren soll aber nur den Wiederaufbau zu niedrigeren (< 30%) Fragmentierungen verwendet werden (das die Datenbank schwerer ist) reduziert die Fragmentierung auf 0%.
Für weitere Informationen siehe https://msdn.microsoft.com/en-us/library/ms189858.aspx

6

ist das modifizierte Skript, das ich von http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding nahm, die ich hier nützlich schreiben gefunden. Obwohl es einen Cursor verwendet und ich weiß, was das Hauptproblem mit Cursorn ist, kann es leicht in eine Cursor-lose Version umgewandelt werden.

Es ist gut dokumentiert und Sie können es leicht lesen und an Ihre Bedürfnisse anpassen.

IF OBJECT_ID('tempdb..#work_to_do') IS NOT NULL 
     DROP TABLE tempdb..#work_to_do 

BEGIN TRY 
--BEGIN TRAN 

use yourdbname 

-- Ensure a USE statement has been executed first. 

    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; 
    DECLARE @pagecount INT; 
    DECLARE @command NVARCHAR(4000); 

    DECLARE @page_count_minimum SMALLINT 
    SET @page_count_minimum = 50 

    DECLARE @fragmentation_minimum FLOAT 
    SET @fragmentation_minimum = 30.0 

-- 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 , 
      page_count AS page_count 
    INTO #work_to_do 
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 
              'LIMITED') 
    WHERE avg_fragmentation_in_percent > @fragmentation_minimum 
      AND index_id > 0 
      AND page_count > @page_count_minimum; 

IF CURSOR_STATUS('global', 'partitions') >= -1 
BEGIN 
PRINT 'partitions CURSOR DELETED' ; 
    CLOSE partitions 
    DEALLOCATE partitions 
END 
-- Declare the cursor for the list of partitions to be processed. 
    DECLARE partitions CURSOR LOCAL 
    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, @pagecount; 

      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; 

      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)); 

      EXEC (@command); 
      --print (@command); //uncomment for testing 

      PRINT N'Rebuilding index ' + @indexname + ' on table ' 
       + @objectname; 
      PRINT N' Fragmentation: ' + CAST(@frag AS VARCHAR(15)); 
      PRINT N' Page Count: ' + CAST(@pagecount AS VARCHAR(15)); 
      PRINT N' '; 
     END; 

-- Close and deallocate the cursor. 
    CLOSE partitions; 
    DEALLOCATE partitions; 

-- Drop the temporary table. 
    DROP TABLE #work_to_do; 
--COMMIT TRAN 

END TRY 
BEGIN CATCH 
--ROLLBACK TRAN 
    PRINT 'ERROR ENCOUNTERED:' + ERROR_MESSAGE() 
END CATCH 
5

zwei Lösungen: Eine einfache und eine erweiterte.

Einführung

Es gibt zwei Lösungen zur Verfügung von der Schwere Ihres Problems abhängig

mit Ihrem eigenen Werte ersetzen, wie folgt:

  • ersetzen XXXMYINDEXXXX mit dem Namen ein Index.
  • Ersetzen Sie XXXMYTABLEXXX durch den Namen einer Tabelle.
  • Ersetzen Sie XXXDATABASENAMEXXX durch den Namen einer Datenbank.

Lösung 1. Indexing

Erstellen Sie alle Indizes für eine Tabelle im Offline-Modus

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD 

einen bestimmten Index im Offline-Modus für eine Tabelle neu erstellen

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD 

Lösung 2. Fragmentierung

Fragmentierung ist ein Problem in Tabellen, die regelmäßig Einträge hinzugefügt und entfernt haben.

prüfen Fragmentierung Prozentsatz

SELECT 
    ips.[index_id] , 
    idx.[name] , 
    ips.[avg_fragmentation_in_percent] 
FROM  
    sys.dm_db_index_physical_stats(DB_ID(N'XXXMYDATABASEXXX'), OBJECT_ID(N'XXXMYTABLEXXX'), NULL, NULL, NULL) AS [ips] 
    INNER JOIN sys.indexes AS [idx] ON [ips].[object_id] = [idx].[object_id] AND [ips].[index_id] = [idx].[index_id] 

Fragmentation 5..30%

Wenn die Fragmentierung Wert von mehr als 5%, aber weniger als 30%, dann lohnt es sich, die Reorganisation Indizes.

reorganisieren alle Indizes für eine Tabelle

ALTER INDEX ALL ON XXXMYTABLEXXX REORGANIZE 

reorganisieren einen bestimmten Index für eine Tabelle

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REORGANIZE 

Fragmentation 30% +

Wenn der Fragmentierung Wert 30% oder höher, dann lohnt es sich, die Indizes im Online-Modus neu zu erstellen.

Erstellen Sie alle Indizes im Online-Modus für eine Tabelle

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON) 

einen bestimmten Index für eine Tabelle im Online-Modus neu erstellen

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON)