none
Index reorganisieren RRS feed

  • Frage

  • Hallo,

    ich habe ein kleines Problem mit dem Punkt Index reorganisieren.

    Wenn ich mir die Fragmentierung der Indices anschaue, dann mekre ich, dass auf meiner DB einige bis zu 99% fragmentiert sind.
    Ich sehe aber nicht, in welcher Tabelle, bzw. welcher Index es ist. Ich sehe hier nur eine Database_ID, eine Object_ID und eine Index_ID.

    Kann mir jemand sagen, wie ich von diesen IDs auf den namen komme?

    Vielen Dank.

    Gruß
    TimoB.
    Mittwoch, 16. Dezember 2009 13:40

Antworten

  • Hallo Timo,

    ich weiss ja nicht, woher Du die Daten erhälst, aber im Normalfall joine die sys.objects, sys.indexes usw. hinzu, z. B.:
    SELECT 
    	o.name AS TableName,
    	i.name AS IndexName,
    	ips.avg_fragmentation_in_percent
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS ips
    INNER JOIN sys.objects AS o
    	ON ips.object_id = o.object_id
    INNER JOIN sys.indexes AS i
    	ON ips.object_id = i.object_id
    	AND ips.index_id = i.index_id 
    WHERE ips.avg_fragmentation_in_percent > 10
    order by ips.object_id, ips.index_id, ips.partition_number
    
    zudem gibt es Funktionen wie DB_NAME , OBJECT_NAME uam.

    In der Dokumentation zu dm_db_index_physical_stats (nur auf den englischen Seiten zu sehen)
    findest Du in den Beispielen ein Skript zum Reorganisieren respektive Neuaufbau.
    Weitere Erläuterungen findest Du unter Neuorganisieren und Neuerstellen von Indizes

    Gruß Elmar
    • Als Antwort markiert TimoB_ Freitag, 18. Dezember 2009 10:14
    Mittwoch, 16. Dezember 2009 16:27
  • Wenn ein neues Thema dann ein neuer Eintrag.

    Die Anwort auf all deine Fragen findest du hier:

    http://realworlddba.wordpress.com/2008/01/27/indexes-to-rebuild-or-reorganize/

    • Als Antwort markiert TimoB_ Dienstag, 8. Februar 2011 12:34
    Dienstag, 8. Februar 2011 12:27
  • Ich habe mit deiner Beschreibung und ein paar anderen Quellen ein neues Statement zusammengebaut.

    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 @command nvarchar(4000); 
    
    -- Tabellen und Indizes aus sys.dm_db_index_physical_stats auslesen
    -- Objekt und Index IDs in Namen konvertieren
    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;
    
    -- Cursor Deklaration
    DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;
    
    OPEN partitions;
    
    -- Schleife durch die einzelnen Partitionen
    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 ist laut MS der Punkt zwischen reorganize und rebuild
        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));
        EXEC (@command);
        PRINT N'Executed: ' + @command;
      END;
    
    -- Cursor schliessen und deallocate
    CLOSE partitions;
    DEALLOCATE partitions;
    
    -- Temporäre Tabelle löschen
    DROP TABLE #work_to_do;
    GO
    
    

    Gruß
    • Als Antwort markiert TimoB_ Freitag, 5. August 2011 14:26
    Dienstag, 8. Februar 2011 15:02

Alle Antworten

  • Hallo Timo,

    ich weiss ja nicht, woher Du die Daten erhälst, aber im Normalfall joine die sys.objects, sys.indexes usw. hinzu, z. B.:
    SELECT 
    	o.name AS TableName,
    	i.name AS IndexName,
    	ips.avg_fragmentation_in_percent
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS ips
    INNER JOIN sys.objects AS o
    	ON ips.object_id = o.object_id
    INNER JOIN sys.indexes AS i
    	ON ips.object_id = i.object_id
    	AND ips.index_id = i.index_id 
    WHERE ips.avg_fragmentation_in_percent > 10
    order by ips.object_id, ips.index_id, ips.partition_number
    
    zudem gibt es Funktionen wie DB_NAME , OBJECT_NAME uam.

    In der Dokumentation zu dm_db_index_physical_stats (nur auf den englischen Seiten zu sehen)
    findest Du in den Beispielen ein Skript zum Reorganisieren respektive Neuaufbau.
    Weitere Erläuterungen findest Du unter Neuorganisieren und Neuerstellen von Indizes

    Gruß Elmar
    • Als Antwort markiert TimoB_ Freitag, 18. Dezember 2009 10:14
    Mittwoch, 16. Dezember 2009 16:27
  • Hallo Elmar,

    danke für die Info. Klappt jetzt super.

    Ich habe vorher folgende Anweisung verwendet:
    select * from sys.dm_db_index_physical_stats(DB_id(),NULL,NULL,NULL,NULL)

    Gruß
    Timo
    Freitag, 18. Dezember 2009 10:14
  • Hi zusammen

     

    Heute bin auf einen anderen Punkt zu diesem Thema gestossen:

    die Indizes in einigen meiner DBs sind extrem groß und fragmentiert.

     

    Was wäre hier nun besser? REORGANIZE oder REBUILT

    Und wie kann ich alle Indizes einer DB reorganisieren bzw. neu aufbauen?

     

    Danke und Gruß

    Dienstag, 8. Februar 2011 12:13
  • Wenn ein neues Thema dann ein neuer Eintrag.

    Die Anwort auf all deine Fragen findest du hier:

    http://realworlddba.wordpress.com/2008/01/27/indexes-to-rebuild-or-reorganize/

    • Als Antwort markiert TimoB_ Dienstag, 8. Februar 2011 12:34
    Dienstag, 8. Februar 2011 12:27
  • Sorry und DANKE.

    Dachte lediglich, dass es hierzu passt.

    Dienstag, 8. Februar 2011 12:34
  • Wenn ein neues Thema dann ein neuer Eintrag.

    Die Anwort auf all deine Fragen findest du hier:

    http://realworlddba.wordpress.com/2008/01/27/indexes-to-rebuild-or-reorganize/


    Ich bin mir nicht sicher, ob das alle Fragen beantwortet, bzw. für alle Environments gleichermassen gültig ist.

    Fwiw, ich habe meine Erfahrungen mal hier zusammengefasst: http://www.insidesql.org/blogs/frankkalis/2011/02/02/index-maintenance-oder-dm_db_index_physical_stats-ist-langsam


    -- Frank Kalis Microsoft SQL Server MVP Webmaster: http://www.insidesql.org
    Dienstag, 8. Februar 2011 12:41
  • Ich habe mit deiner Beschreibung und ein paar anderen Quellen ein neues Statement zusammengebaut.

    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 @command nvarchar(4000); 
    
    -- Tabellen und Indizes aus sys.dm_db_index_physical_stats auslesen
    -- Objekt und Index IDs in Namen konvertieren
    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;
    
    -- Cursor Deklaration
    DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;
    
    OPEN partitions;
    
    -- Schleife durch die einzelnen Partitionen
    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 ist laut MS der Punkt zwischen reorganize und rebuild
        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));
        EXEC (@command);
        PRINT N'Executed: ' + @command;
      END;
    
    -- Cursor schliessen und deallocate
    CLOSE partitions;
    DEALLOCATE partitions;
    
    -- Temporäre Tabelle löschen
    DROP TABLE #work_to_do;
    GO
    
    

    Gruß
    • Als Antwort markiert TimoB_ Freitag, 5. August 2011 14:26
    Dienstag, 8. Februar 2011 15:02