Przejdź do treści
Powrót do Centrum Pomocy
SQL Server
Porównania

SQL Server — fragmentacja indeksów: REBUILD vs REORGANIZE. Kiedy stosować które polecenie?

W indeksach typu B-tree (rowstore) SQL Server przechowuje dane na 8-kilobajtowych stronach. Gdy wstawiasz, aktualizujesz lub usuwasz wiersze, silnik automatyczn

11 min czytania·Zaktualizowano dzisiaj
Faktura VAT 23% + KSeFDostawa 1-3 min e-mailemGwarancja działania klucza5,0 / 5,0(KluczeSoft)

Fragmentacja indeksów w SQL Server to zjawisko, w którym fizyczne uporządkowanie stron indeksu przestaje odpowiadać logicznej kolejności kluczy — co prowadzi do zwiększonej liczby operacji I/O i spadku wydajności zapytań. Serwer udostępnia dwa narzędzia do walki z tym problemem: ALTER INDEX ... REORGANIZE (lżejsze, zawsze online) oraz ALTER INDEX ... REBUILD (gruntowne, z możliwością działania offline lub online). Wybór między nimi zależy od stopnia fragmentacji, gęstości stron (page density), wielkości tabeli, okna serwisowego oraz wersji SQL Server.

W skrócie

  • REORGANIZE — defragmentuje tylko poziom liści (leaf level), zawsze online, nie blokuje zapytań, nadaje się do fragmentacji 5–30%. Postęp jest zachowywany przy przerwaniu.
  • REBUILD — usuwa i odtwarza indeks, czyści wszystkie poziomy (B-tree), domyślnie offline (blokuje dostęp do tabeli), od SQL Server 2005 dostępny ONLINE = ON. Zalecany przy fragmentacji >30%.
  • Microsoft od 2022 roku odchodzi od sztywnych progów procentowych na rzecz podejścia empirycznego — mierz wpływ na wydajność przez Query Store, zanim podejmiesz decyzję o konserwacji.
  • Od SQL Server 2019: REBUILD dla columnstore dostępny online (ONLINE = ON); od 2017: REBUILD dla rowstore może być wznawialny (RESUMABLE).
  • Kluczowa pułapka: wiele zysków wydajnościowych po REBUILD wynika tak naprawdę z aktualizacji statystyk FULLSCAN, a nie z samej defragmentacji — tańszym rozwiązaniem bywa samo UPDATE STATISTICS.

Czym jest fragmentacja indeksów w SQL Server

W indeksach typu B-tree (rowstore) SQL Server przechowuje dane na 8-kilobajtowych stronach. Gdy wstawiasz, aktualizujesz lub usuwasz wiersze, silnik automatycznie modyfikuje strony — może dojść do podziału strony (page split), gdy nowa wartość nie mieści się na istniejącej stronie. Po podziale strony trafiają w różne fizyczne lokalizacje na dysku, a logiczna kolejność kluczy rozjeżdża się z fizycznym rozmieszczeniem — to właśnie fragmentacja logiczna (mierzona jako avg_fragmentation_in_percent w sys.dm_db_index_physical_stats).

Drugim wymiarem problemu jest gęstość stron (avg_page_space_used_in_percent) — im niższa, tym więcej stron trzeba odczytać z dysku dla tej samej ilości danych. Według dokumentacji Microsoftu z marca 2026 roku, niska gęstość stron często ma większy negatywny wpływ na wydajność niż sama fragmentacja — co jest znacznie mniej znanym faktem wśród administratorów.

Jak zmierzyć fragmentację — sys.dm_db_index_physical_stats

Podstawowym narzędziem diagnostycznym jest funkcja sys.dm_db_index_physical_stats. Oto sprawdzone zapytanie zwracające fragmentację i gęstość stron dla wszystkich indeksów w bazie:

SELECT
    OBJECT_SCHEMA_NAME(ips.object_id) AS schemat,
    OBJECT_NAME(ips.object_id)        AS tabela,
    i.name                             AS indeks,
    i.type_desc                        AS typ,
    ips.avg_fragmentation_in_percent   AS fragmentacja_proc,
    ips.avg_page_space_used_in_percent AS gestosc_stron_proc,
    ips.page_count                     AS liczba_stron
FROM sys.dm_db_index_physical_stats(DB_ID(), DEFAULT, DEFAULT, DEFAULT, 'SAMPLED') AS ips
INNER JOIN sys.indexes AS i
    ON ips.object_id = i.object_id AND ips.index_id = i.index_id
ORDER BY ips.page_count DESC;

Tryb SAMPLED jest szybki i wystarczający do rutynowego monitoringu. Tryb DETAILED skanuje każdą stronę — dokładniejszy, ale znacząco wolniejszy przy dużych tabelach.

W przypadku indeksów columnstore fragmentację definiuje się inaczej: jako stosunek wierszy oznaczonych jako usunięte do wszystkich wierszy w skompresowanych grupach wierszy. Do jej pomiaru służy sys.dm_db_column_store_row_group_physical_stats.

REORGANIZE — lekka defragmentacja always-online

ALTER INDEX ... REORGANIZE działa wyłącznie na poziomie liści indeksów rowstore. Fizycznie przepina strony, przywracając ich logiczną kolejność, oraz kompaktuje strony do poziomu FILLFACTOR zdefiniowanego dla indeksu.

Kluczowe cechy REORGANIZE:

CechaWartość
Poziomy indeksuTylko leaf level
BlokowanieBrak blokad obiektowych — zawsze online
TransakcyjnośćPostęp zachowany przy przerwaniu — można wznawiać
Log transakcyjnyNiskie zużycie — operacje małymi porcjami
StatystykiNie są aktualizowane
Przestrzeń dyskowaWymaga wolnego miejsca w tym samym pliku danych (alokuje tymczasowe strony robocze)
ALLOW_PAGE_LOCKS = OFF❌ Niedozwolone

Kiedy stosować: fragmentacja 5–30%, ograniczone okno serwisowe, środowiska produkcyjne bez możliwości przestoju, bazy Azure SQL (gdzie resource governance ogranicza zasoby).

REBUILD — gruntowna przebudowa indeksu

ALTER INDEX ... REBUILD usuwa indeks i tworzy go od nowa. Oznacza to pełne czyszczenie fragmentacji na wszystkich poziomach drzewa B oraz przywrócenie gęstości stron zgodnie z FILLFACTOR.

Kluczowe cechy REBUILD:

CechaWartość
Poziomy indeksuWszystkie (root, intermediate, leaf)
Blokowanie (OFFLINE)Wyłączna blokada obiektu na czas operacji — tabela niedostępna
Blokowanie (ONLINE)Krótka blokada tylko na końcu operacji (od SQL 2005 dla Enterprise/Developer)
WznawialnośćRESUMABLE = ON od SQL Server 2017 (rowstore) — można wstrzymać i wznowić
Log transakcyjnyDuże zużycie — pełna kopia indeksu
StatystykiAutomatycznie aktualizowane z FULLSCAN (dla niepartycjonowanych, jednorazowych rebuildów)
Przestrzeń dyskowaWymaga miejsca na dwie kopie indeksu (stara + nowa)
Columnstore onlineOd SQL Server 2019 (ONLINE = ON)

Kiedy stosować: fragmentacja >30%, niska gęstość stron (<70%), potrzeba aktualizacji statystyk FULLSCAN, zmiana FILLFACTOR, odbudowa po korupcji danych (tylko offline nonclustered), zmiana partycjonowania lub filegroup.

REBUILD vs REORGANIZE — tabela porównawcza

KryteriumREORGANIZEREBUILD (OFFLINE)REBUILD (ONLINE)
Zakres defragmentacjiTylko leaf levelWszystkie poziomyWszystkie poziomy
Blokowanie tabeli❌ Brak✅ Pełna blokada⚠ Krótka na końcu
Dostępność tabeli w trakcie✅ Pełna❌ Niedostępna✅ Dostępna
Zużycie logu transakcyjnegoNiskieWysokieWysokie
Aktualizacja statystyk❌ Nie✅ FULLSCAN (z zastrzeż.)✅ FULLSCAN (z zastrzeż.)
Wznawialność (RESUMABLE)ZawszeTylko ONLINE + od 2017✅ od SQL 2017
Przestrzeń na drugą kopię❌ Nie wymaga✅ Wymagana✅ Wymagana
Możliwość zmiany FILLFACTOR❌ Nie (tylko kompaktuje)✅ Tak✅ Tak
Szybkość działaniaWolniejsza (stronami)NajszybszaWolniejsza niż offline
Nadaje się do Azure SQL✅ (resource governance)❌ Niezalecane✅ Tak, zwłaszcza resumable
Działa z ALLOW_PAGE_LOCKS = OFF❌ Nie✅ Tak✅ Tak
Kompaktowanie LOBOpcjonalnieAutomatycznieAutomatycznie

Progi fragmentacji — tradycyjna heurystyka vs. współczesne zalecenia Microsoftu

Tradycyjne progi (wciąż stosowane w wielu skryptach konserwacyjnych)

FragmentacjaZalecana akcja
0–5%Brak działania
5–30%REORGANIZE
>30%REBUILD

Te progi pochodzą ze starszych wersji SQL Server i sprawdzają się jako punkt startowy, szczególnie w mniejszych środowiskach on-premises.

Stanowisko Microsoftu (dokumentacja z marca 2026)

Microsoft w oficjalnej dokumentacji wyraźnie odchodzi od sztywnych progów. Kluczowe cytaty z docs:

"Index maintenance decisions should be made after considering multiple factors in the specific context of each workload (...). They shouldn't be based on fixed fragmentation or page density thresholds alone."

"Don't assume that index maintenance always noticeably improves your workload. Measure the specific impact of reorganizing or rebuilding indexes on query performance in your workload. Query Store is a good way to measure the 'before maintenance' and 'after maintenance' performance using the A/B testing technique."

Microsoft zaleca strategię:

  1. Zmierz wydajność zapytań przed i po konserwacji (Query Store).
  2. Sprawdź, czy sam UPDATE STATISTICS ... WITH FULLSCAN nie daje tego samego efektu co REBUILD (często daje!).
  3. Utrzymuj tylko te indeksy, które faktycznie degradują wydajność — nie wszystkie w bazie.
  4. Nie trzymaj się sztywnego harmonogramu — monitoruj i działaj, gdy fragmentacja zaczyna szkodzić.

Dlaczego REBUILD często „działa cuda" — a to nie zasługa samej defragmentacji

To jedna z największych pułapek w administracji SQL Server. REBUILD automatycznie aktualizuje statystyki kolumn kluczowych indeksu z próbkowaniem FULLSCAN. Gdy statystyki są nieaktualne, optymalizator zapytań generuje nieoptymalne plany. Po REBUILD — nowe, lepsze plany. Administratorzy przypisują wzrost wydajności defragmentacji, tymczasem ten sam efekt można osiągnąć kilkunastokrotnie mniejszym kosztem przez samo UPDATE STATISTICS.

Nowości w SQL Server 2022/2025 istotne dla zarządzania indeksami

  • RESUMABLE rebuild (od 2017) — możliwość wstrzymania ALTER INDEX ... REBUILD WITH (ONLINE = ON, RESUMABLE = ON) i wznowienia go później. Kluczowe przy wielogodzinnych rebuildach, gdzie przerwanie (failover, restart) nie powinno marnować postępu.
  • Automatic Index Compaction (preview) — w SQL Server 2025 dostępna jest eksperymentalna funkcja automatycznego kompaktowania indeksów, stanowiąca niskonakładową alternatywę dla ręcznego REORGANIZE.
  • Columnstore background merge (od 2019) — tuple-mover z zadaniem w tle automatycznie łączy małe grupy wierszy w columnstore, co w wielu przypadkach eliminuje potrzebę ręcznego REORGANIZE.
  • MAXDOP przy REBUILD — od SQL Server 2016 można jawnie ustawić MAXDOP dla operacji indeksowych, kontrolując zużycie CPU.

Przykłady składni T-SQL

Pomiar fragmentacji dla pojedynczej tabeli:

SELECT avg_fragmentation_in_percent, avg_page_space_used_in_percent, page_count
FROM sys.dm_db_index_physical_stats(
    DB_ID(), OBJECT_ID('dbo.MojaTabela'), NULL, NULL, 'SAMPLED');

Reorganizacja pojedynczego indeksu:

ALTER INDEX IX_MojaTabela_Kolumna ON dbo.MojaTabela REORGANIZE;

Reorganizacja wszystkich indeksów na tabeli:

ALTER INDEX ALL ON dbo.MojaTabela REORGANIZE;

Rebuild offline (najszybszy, blokuje tabelę):

ALTER INDEX PK_MojaTabela ON dbo.MojaTabela REBUILD;

Rebuild online z wznawialnością (produkcja, duże tabele):

ALTER INDEX PK_MojaTabela ON dbo.MojaTabela
REBUILD WITH (ONLINE = ON, RESUMABLE = ON, MAXDOP = 4);

Rebuild z nowym FILLFACTOR i SORT_IN_TEMPDB:

ALTER INDEX ALL ON dbo.MojaTabela
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON);

Czego unikać — typowe błędy przy konserwacji indeksów

  1. Rebuildowanie wszystkiego w harmonogramie nocnym bez sprawdzenia fragmentacji. Przy nowoczesnym sprzęcie (SSD/NVMe, storage klasy enterprise) różnica między odczytem sekwencyjnym a losowym jest znacznie mniejsza niż kiedyś — fragmentacja często nie ma żadnego mierzalnego wpływu. Marnujesz zasoby i generujesz ogromny log transakcyjny.

  2. Używanie REORGANIZE z ALLOW_PAGE_LOCKS = OFF — to niedozwolone; operacja zakończy się błędem.

  3. Brak miejsca na drugą kopię indeksu przy REBUILD — musisz mieć w filegroup miejsce równe rozmiarowi oryginalnego indeksu. Przy braku miejsca operacja zakończy się błędem 1105.

  4. Ignorowanie gęstości stron. Indeks może mieć 2% fragmentacji, ale 55% page density — wtedy baza wykonuje niemal dwukrotnie więcej odczytów niż potrzebuje.

  5. Rebuild małych indeksów (<128 extents, ok. 8 MB) — często nie redukuje fragmentacji, ponieważ strony małych indeksów są przechowywane na mixed extents współdzielonych z nawet 8 innymi obiektami.

  6. REBUILD kolumnowego indeksu klastrowanego OFFLINE na SQL Server 2017 i starszych — tabela będzie całkowicie niedostępna nawet przy NOLOCK czy RCSI.

Częste pytania

Co to jest fragmentacja indeksu w SQL Server?

To niezgodność między logiczną kolejnością stron indeksu (wynikającą z wartości kluczy) a ich fizycznym rozmieszczeniem na dysku. Powstaje w wyniku operacji INSERT, UPDATE i DELETE, które powodują podziały stron (page splits). Prowadzi do większej liczby operacji I/O przy skanach zakresowych i pełnych skanach indeksu, ponieważ zamiast kilku dużych odczytów sekwencyjnych serwer wykonuje wiele małych odczytów losowych.

Jak sprawdzić fragmentację indeksów w SQL Server?

Użyj funkcji sys.dm_db_index_physical_stats z parametrem trybu 'SAMPLED' (szybko) lub 'DETAILED' (dokładnie, ale skanuje każdą stronę). Kolumna avg_fragmentation_in_percent pokazuje fragmentację logiczną, a avg_page_space_used_in_percent — gęstość stron. Dla indeksów columnstore użyj sys.dm_db_column_store_row_group_physical_stats.

Jaka jest różnica między REORGANIZE a REBUILD?

REORGANIZE defragmentuje tylko poziom liści indeksu, działa zawsze online i nie blokuje dostępu do tabeli. Jest mniej zasobożerne, ale wolniejsze i nie aktualizuje statystyk. REBUILD usuwa i tworzy indeks od nowa, czyści wszystkie poziomy drzewa B, domyślnie blokuje tabelę (offline), wymaga miejsca na dwie kopie indeksu, ale automatycznie aktualizuje statystyki z FULLSCAN. Od SQL Server 2005 dostępny jest tryb ONLINE, a od 2017 — wznawialny (RESUMABLE).

Przy jakiej fragmentacji robić REBUILD, a przy jakiej REORGANIZE?

Tradycyjne progi to: 0–5% — nic nie rób, 5–30% — REORGANIZE, >30% — REBUILD. Microsoft od 2022 roku odradza jednak ślepe trzymanie się tych wartości i zaleca pomiar faktycznego wpływu fragmentacji na wydajność zapytań przez Query Store. W wielu środowiskach — szczególnie na nowoczesnych macierzach SSD i w Azure SQL — umiarkowana fragmentacja nie przekłada się na odczuwalny spadek wydajności.

Czy REORGANIZE aktualizuje statystyki indeksu?

Nie. REORGANIZE w ogóle nie dotyka statystyk. REBUILD natomiast aktualizuje statystyki kolumn kluczowych indeksu z próbkowaniem FULLSCAN — chyba że indeks jest partycjonowany, rebuild jest wznawialny (RESUMABLE) lub użyto STATISTICS_NORECOMPUTE = ON. To ważne: wiele obserwowanych „popraw wydajności" po REBUILD wynika z aktualizacji statystyk, nie z defragmentacji.

Czy REBUILD online blokuje tabelę?

Przy ONLINE = ON blokada obiektowa (Schema Modification Lock) jest zakładana tylko na bardzo krótki moment na końcu operacji — by zamienić stary indeks nowym. W trakcie trwania rebuildu tabela jest dostępna dla zapytań SELECT, INSERT, UPDATE i DELETE. Należy jednak pamiętać, że operacje modyfikacji danych w trakcie online rebuildu muszą utrzymywać dodatkową kopię indeksu, co powoduje niewielki narzut wydajnościowy.

Co z indeksami columnstore — czy też wymagają REBUILD?

Od SQL Server 2016 REORGANIZE dla columnstore wykonuje online te same operacje co REBUILD (usuwa logicznie usunięte wiersze, łączy małe grupy wierszy). Od SQL Server 2019 działa też automatyczny tuple-mover w tle, który dodatkowo redukuje potrzebę ręcznej konserwacji. REBUILD columnstore jest wskazany głównie przy zmianie partycjonowania lub po masowym ładowaniu danych, a od wersji 2019 może działać w trybie online.

Wydajny SQL Server zaczyna się od właściwej licencji

Prawidłowe zarządzanie indeksami to podstawa wydajności każdej bazy SQL Server — ale wszystko zaczyna się od legalnego, w pełni funkcjonalnego środowiska. Jeśli potrzebujesz licencji na Windows Server pod instalację SQL Server lub Microsoft SQL Server w wersji Standard/Enterprise do środowiska produkcyjnego, sprawdź ofertę KluczeSoft:

Licencje Windows Server — od 199 zł — pełnoprawne klucze do Windows Server 2022 i 2025, niezbędne przy wdrożeniach on-premises SQL Server.

(KluczeSoft jest niezależnym sprzedawcą używanego oprogramowania Microsoft — legalność odsprzedaży w UE potwierdza wyrok TSUE w sprawie C-128/11 UsedSoft. KluczeSoft nie jest powiązany z Microsoft Corporation.)

Najczęściej zadawane pytania

To niezgodność między logiczną kolejnością stron indeksu (wynikającą z wartości kluczy) a ich fizycznym rozmieszczeniem na dysku. Powstaje w wyniku operacji INSERT, UPDATE i DELETE, które powodują podziały stron (page splits). Prowadzi do większej liczby operacji I/O przy skanach zakresowych i pełnych skanach indeksu, ponieważ zamiast kilku dużych odczytów sekwencyjnych serwer wykonuje wiele małych odczytów losowych.
Użyj funkcji `sys.dm_db_index_physical_stats` z parametrem trybu `'SAMPLED'` (szybko) lub `'DETAILED'` (dokładnie, ale skanuje każdą stronę). Kolumna `avg_fragmentation_in_percent` pokazuje fragmentację logiczną, a `avg_page_space_used_in_percent` — gęstość stron. Dla indeksów columnstore użyj `sys.dm_db_column_store_row_group_physical_stats`.
REORGANIZE defragmentuje tylko poziom liści indeksu, działa zawsze online i nie blokuje dostępu do tabeli. Jest mniej zasobożerne, ale wolniejsze i nie aktualizuje statystyk. REBUILD usuwa i tworzy indeks od nowa, czyści wszystkie poziomy drzewa B, domyślnie blokuje tabelę (offline), wymaga miejsca na dwie kopie indeksu, ale automatycznie aktualizuje statystyki z FULLSCAN. Od SQL Server 2005 dostępny jest tryb ONLINE, a od 2017 — wznawialny (RESUMABLE).
Tradycyjne progi to: 0–5% — nic nie rób, 5–30% — REORGANIZE, >30% — REBUILD. Microsoft od 2022 roku odradza jednak ślepe trzymanie się tych wartości i zaleca pomiar faktycznego wpływu fragmentacji na wydajność zapytań przez Query Store. W wielu środowiskach — szczególnie na nowoczesnych macierzach SSD i w Azure SQL — umiarkowana fragmentacja nie przekłada się na odczuwalny spadek wydajności.
Nie. REORGANIZE w ogóle nie dotyka statystyk. REBUILD natomiast aktualizuje statystyki kolumn kluczowych indeksu z próbkowaniem FULLSCAN — chyba że indeks jest partycjonowany, rebuild jest wznawialny (RESUMABLE) lub użyto `STATISTICS_NORECOMPUTE = ON`. To ważne: wiele obserwowanych „popraw wydajności" po REBUILD wynika z aktualizacji statystyk, nie z defragmentacji.
Przy `ONLINE = ON` blokada obiektowa (Schema Modification Lock) jest zakładana tylko na bardzo krótki moment na końcu operacji — by zamienić stary indeks nowym. W trakcie trwania rebuildu tabela jest dostępna dla zapytań SELECT, INSERT, UPDATE i DELETE. Należy jednak pamiętać, że operacje modyfikacji danych w trakcie online rebuildu muszą utrzymywać dodatkową kopię indeksu, co powoduje niewielki narzut wydajnościowy.
Od SQL Server 2016 REORGANIZE dla columnstore wykonuje online te same operacje co REBUILD (usuwa logicznie usunięte wiersze, łączy małe grupy wierszy). Od SQL Server 2019 działa też automatyczny `tuple-mover` w tle, który dodatkowo redukuje potrzebę ręcznej konserwacji. REBUILD columnstore jest wskazany głównie przy zmianie partycjonowania lub po masowym ładowaniu danych, a od wersji 2019 może działać w trybie online.

Czy ten artykuł był pomocny?