Unterschiedliche Ergebnisse beim Neuerstellen eines Index online und offline

7

Ich habe einen nicht gruppierten, nicht eindeutigen Index für eine Fremdschlüsselspalte vom Typ bigint. Wenn ich den Index online neu erstelle, sinkt die durchschnittliche Fragmentierung auf 3% mit 2 Fragmenten und 30 Seiten.

Wenn ich denselben Wiederherstellungsindex offline ausführe, beträgt die durchschnittliche Fragmentierung 25% mit 4 Fragmenten und 28 Seiten.

Ich denke das FILLFACTORist 90. Die Datenbank ist 77GB. Ich bin kein DBA oder ähnliches, ich bin ein C # -Entwickler, daher bin ich nicht mit allen Begriffen vertraut. In dieser Tabelle gibt es keine Aktivität. Dies tritt in unserer Entwicklungsumgebung auf.

Dies ist die Abfrage mit redigierten Namen.

ALTER INDEX [IX] ON [dbo].[Table]
REBUILD WITH
(
    PAD_INDEX  = OFF, 
    STATISTICS_NORECOMPUTE  = OFF, 
    ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON, 
    ONLINE = ON, 
    SORT_IN_TEMPDB = ON
);

Was könnte diesen Unterschied verursachen? Die gleiche Situation tritt bei mehreren Tabellen auf.

RLT
quelle
1
@RLT Wenn Sie mehr über Indizes aus der Sicht eines Entwicklers erfahren möchten
Max Vernon
Beim genaueren Lesen vermute ich, dass dies nur auf die extrem geringe Größe Ihres Index zurückzuführen ist.
JNK

Antworten:

3

Dies ist keineswegs eine vollständige Antwort, kann aber die Dinge ein wenig bewegen, wenn Sie etwas Ähnliches ausprobieren und Ihre Ergebnisse melden.

Ich konnte sie nicht reproduzieren. Mit der folgenden Testtabelle

CREATE TABLE [dbo].[Table]
(
Col BIGINT
)

CREATE NONCLUSTERED INDEX IX ON [dbo].[Table](Col)

INSERT INTO [dbo].[Table]
SELECT top 12000 ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values v1, master..spt_values v2

Und mehrere Läufe des folgenden Skripts

USE FragTest;

DECLARE @DbccPage TABLE (
  ParentObject VARCHAR(255),
  Object       VARCHAR(255),
  Field        VARCHAR(255),
  VALUE        VARCHAR(255))

DECLARE @sp_index_info TABLE (
  PageFID         TINYINT,
  PagePID         INT,
  IAMFID          TINYINT,
  IAMPID          INT,
  ObjectID        INT,
  IndexID         TINYINT,
  PartitionNumber TINYINT,
  PartitionID     BIGINT,
  iam_chain_type  VARCHAR(30),
  PageType        TINYINT,
  IndexLevel      TINYINT,
  NextPageFID     TINYINT,
  NextPagePID     INT,
  PrevPageFID     TINYINT,
  PrevPagePID     INT,
  PRIMARY KEY (PageFID, PagePID));

DECLARE @I INT = 0

WHILE @I < 2
  BEGIN
      DECLARE @Online VARCHAR(3) = CASE
          WHEN @I = 0 THEN 'OFF'
          ELSE 'ON'
        END

      EXEC('ALTER INDEX [IX] ON [dbo].[Table]
REBUILD WITH
(
    PAD_INDEX  = OFF, 
    STATISTICS_NORECOMPUTE  = OFF, 
    ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON, 
    ONLINE = ' + @Online + ', 
    SORT_IN_TEMPDB = ON
);')

      INSERT INTO @sp_index_info
      EXEC ('DBCC IND ( FragTest, ''[dbo].[Table]'', 2)' );

      ; WITH T
           AS (SELECT *,
                      PagePID - ROW_NUMBER() OVER (PARTITION BY PageType, IndexLevel ORDER BY PagePID) AS Grp
               FROM   @sp_index_info)
      SELECT PageType,
             MIN(PagePID) AS StartPID,
             MAX(PagePID) AS EndPID,
             COUNT(*)     AS [count],
             IndexLevel
      FROM   T
      GROUP  BY Grp,
                PageType,
                IndexLevel
      ORDER  BY PageType DESC,
                StartPID

      DECLARE @DynSQL NVARCHAR(4000)

      SELECT @DynSQL = N'DBCC PAGE (FragTest, ' + LTRIM(PageFID) + ',' + LTRIM(PagePID) + ',3) WITH TABLERESULTS'
      FROM   @sp_index_info
      WHERE  PageType = 10

      INSERT INTO @DbccPage
      EXEC(@DynSQL)

      SELECT VALUE AS SinglePageAllocations
      FROM   @DbccPage
      WHERE  VALUE <> '(0:0)'
             AND Object LIKE '%IAM: Single Page Allocations%'

      SELECT avg_page_space_used_in_percent,
             avg_fragmentation_in_percent,
             fragment_count,
             page_count,
             @Online                                                   AS [Online],
             (SELECT COUNT(*)
              FROM   @DbccPage
              WHERE  VALUE <> '(0:0)'
                     AND Object LIKE '%IAM: Single Page Allocations%') AS SinglePageAllocations
      FROM   sys.dm_db_index_physical_stats(db_id(), object_id('[dbo].[Table]'), 2, NULL, 'DETAILED')
      WHERE  index_level = 0

      DELETE FROM @sp_index_info

      DELETE FROM @DbccPage

      SET @I = @I + 1
  END 

Ich habe durchweg Ergebnisse wie

Online = AUS

PageType StartPID    EndPID      count       IndexLevel
-------- ----------- ----------- ----------- ----------
10       119         119         1           NULL
2        2328        2351        24          0
2        2352        2352        1           1
2        2384        2392        9           0


SinglePageAllocations
----------------------

(0 row(s) affected)


avg_page_space_used_in_percent avg_fragmentation_in_percent fragment_count       page_count           Online SinglePageAllocations
------------------------------ ---------------------------- -------------------- -------------------- ------ ---------------------
98.8139362490734               0                            2                    33                   OFF    0

Online = EIN

PageType StartPID    EndPID      count       IndexLevel
-------- ----------- ----------- ----------- ----------
10       115         115         1           NULL
2        114         114         1           0
2        118         118         1           1
2        2416        2449        34          0



SinglePageAllocations
-----------------------
(1:114)
(1:118)


avg_page_space_used_in_percent avg_fragmentation_in_percent fragment_count       page_count           Online SinglePageAllocations
------------------------------ ---------------------------- -------------------- -------------------- ------ ---------------------
97.4019644180875               2.85714285714286             2                    35                   ON     2

Zumindest im Test habe ich die Unterschiede zwischen den beiden in Bezug auf die Fragmentierung ausgeglichen (obwohl ich ähnlich wie bei Ihrem Test festgestellt habe, dass die Online-Neuerstellung des Index zu einer höheren Seitenzahl geführt hat).

Ich fand heraus, dass die Online = OFFVersion immer einheitliche Ausmaße verwendete und keine einzelnen Seitenzuordnungen hatte, während Online = ONdie Indexstammseite und die erste Indexblattseite immer in gemischten Ausmaßen zu sein schienen.

Wenn Sie die erste Indexblattseite in gemischtem Umfang und den Rest in zusammenhängenden einheitlichen Ausmaßen platzieren, wird eine Fragmentanzahl von 2 erstellt.

Die Online = OFFVersion vermeidet das Fragment, das durch die einzelne Indexblattseite verursacht wird, aber die Kontiguität der Blattseiten wird durch die Indexstammseite unterbrochen, die dieselben Ausmaße aufweist, und auch diese hat eine Fragmentanzahl von 2.

Ich habe meinen Test in einer neu erstellten Datenbank mit 1 GB freiem Speicherplatz und ohne gleichzeitige Aktivität ausgeführt. Möglicherweise ist die Online = OFFVersion anfälliger für gleichzeitige Zuweisungen, was dazu führt, dass ihr nicht zusammenhängende einheitliche Ausmaße zugewiesen werden.

Martin Smith
quelle
-6

Die Fragmentierung hängt von Ihrem Dateisystem ab. Lokal haben Sie möglicherweise Millionen von Dateien, die den meisten Speicherplatz beanspruchen, und es gibt einige freie Speicherplätze auf einer Festplatte, auf denen einige Daten gespeichert werden können. Wenn also ganze Indexdaten nicht in einem Raum gespeichert werden können, werden sie in mehrere Teile fragmentiert. Online haben Sie möglicherweise eine leere Festplatte mit vielen nicht zugewiesenen Speicherplatzteilen, die zum Speichern der gesamten Tabelle oder des Index oder was auch immer verwendet werden können


quelle
1
Die Indexfragmentierung ist ähnlich, aber weder verwandt noch das Ergebnis der Dateifragmentierung auf Datenträgern.
Ypercubeᵀᴹ