it-swarm.dev

Dlaczego moja baza danych jest nadal fragmentowana po tym, jak wszystko odbudowałem i ponownie zindeksowałem?

Mam bazę danych, którą próbowałem defragmentować wszystkie tabele jednocześnie, uruchamiając ten T-SQL:

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

A następnie kopiowanie i wklejanie danych wyjściowych do nowego okna zapytania i uruchamianie tego. Nie dostałem żadnych błędów, ale nadal mam fragmentację. Próbowałem też uruchomić oba polecenia osobno i nadal mam fragmentację. waga: Dowiedziałem się, że REORGANIZE jest niepotrzebny przez Aarona i wiem, że mogę zautomatyzować to za pomocą dynamicznego SQL.

Uruchomiłem to, aby stwierdzić, że nadal mam fragmentację:

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

I mam:

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

Wiem, że brakuje mi czegoś naprawdę podstawowego, ale nie wiem co.

41
Justin Dearing

Stoły są małe. Liczba stron w twoich tabelach to:

11, 8, 6, 5, 13, 8, 10

Zajmują łącznie 480 KB. Nie ma dosłownie nic do defragmentacji.

Edycja: To wymaga trochę więcej wyjaśnień.

Nowej tabeli lub indeksowi zwykle przypisuje się pierwsze 8 stron z mieszanego, a nie jednolitego zakresu. Tak więc możliwe jest przydzielenie każdej z pierwszych 8 stron z różnych zakresów mieszanych. Tabela lub indeks zajmujący 8 stron może zatem mieć 8 fragmentów, po 1 na każdym z 8 różnych mieszanych zakresów.

Powszechnie stosowane skrypty defragmentacyjne (kilka przykładów poniżej) z tego powodu wykluczają małe tabele. IIRC <500 stron znajduje się na jednej lub obu z nich. Przy tych rozmiarach defragmentacja jest bardzo niewielka, a dane dotyczące fragmentacji są potencjalnie zniekształcone przez przydziały o mieszanym zakresie.

38

Cytat z „ Najważniejsze wskazówki dotyczące defragmentacji indeksu Microsoft SQL Server 20 ”:

„Fragmentacja wpływa na operacje wejścia/wyjścia na dysku. Dlatego skup się na większych indeksach, ponieważ ich strony nie są buforowane przez SQL Server. Użyj liczby stron zgłoszonej przez DBCC SHOWCONTIG, aby dowiedzieć się o wielkości indeksów (każda strona jest 8 KB). Zasadniczo nie należy przejmować się poziomem fragmentacji indeksów zawierających mniej niż 1000 stron. W testach indeksy zawierające ponad 10 000 stron osiągnęły wzrost wydajności, przy czym największe zyski na indeksach ze znacznie większą liczbą stron (ponad 50 000 stron) . ”

Ten rodzaj odpowiedzi odpowiada na twoje pytanie i wspiera odpowiedzi Marka i Aarona.

Dobre informacje na temat fragmentacji indeksu można znaleźć w następujących artykułach Brenta Ozara:

Ponadto ... ocean świetnych informacji o indeksach w ogóle (także o problemach z fragmentacją) można znaleźć na blog Kimberly Tripp .

20
Marian

To nie ma na celu odpowiedzieć na twoje pytanie, ale nigdy nie zmieści się w komentarzu. Możesz zbudować ten skrypt dynamicznie, bez konieczności kopiowania i wklejania danych wyjściowych do innego okna. Biorąc pod uwagę, że absolutnie nie ma powodu, aby REORGANIZE, a następnie REBUILD:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;
12
Aaron Bertrand