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 samoUPDATE 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:
| Cecha | Wartość |
|---|---|
| Poziomy indeksu | Tylko leaf level |
| Blokowanie | Brak blokad obiektowych — zawsze online |
| Transakcyjność | Postęp zachowany przy przerwaniu — można wznawiać |
| Log transakcyjny | Niskie zużycie — operacje małymi porcjami |
| Statystyki | Nie są aktualizowane |
| Przestrzeń dyskowa | Wymaga 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:
| Cecha | Wartość |
|---|---|
| Poziomy indeksu | Wszystkie (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 transakcyjny | Duże zużycie — pełna kopia indeksu |
| Statystyki | Automatycznie aktualizowane z FULLSCAN (dla niepartycjonowanych, jednorazowych rebuildów) |
| Przestrzeń dyskowa | Wymaga miejsca na dwie kopie indeksu (stara + nowa) |
| Columnstore online | Od 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
| Kryterium | REORGANIZE | REBUILD (OFFLINE) | REBUILD (ONLINE) |
|---|---|---|---|
| Zakres defragmentacji | Tylko leaf level | Wszystkie poziomy | Wszystkie 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 transakcyjnego | Niskie | Wysokie | Wysokie |
| Aktualizacja statystyk | ❌ Nie | ✅ FULLSCAN (z zastrzeż.) | ✅ FULLSCAN (z zastrzeż.) |
| Wznawialność (RESUMABLE) | Zawsze | Tylko 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łania | Wolniejsza (stronami) | Najszybsza | Wolniejsza 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 LOB | Opcjonalnie | Automatycznie | Automatycznie |
Progi fragmentacji — tradycyjna heurystyka vs. współczesne zalecenia Microsoftu
Tradycyjne progi (wciąż stosowane w wielu skryptach konserwacyjnych)
| Fragmentacja | Zalecana 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ę:
- Zmierz wydajność zapytań przed i po konserwacji (Query Store).
- Sprawdź, czy sam
UPDATE STATISTICS ... WITH FULLSCANnie daje tego samego efektu co REBUILD (często daje!). - Utrzymuj tylko te indeksy, które faktycznie degradują wydajność — nie wszystkie w bazie.
- 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-moverz 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ć
MAXDOPdla 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
-
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.
-
Używanie
REORGANIZEzALLOW_PAGE_LOCKS = OFF— to niedozwolone; operacja zakończy się błędem. -
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.
-
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.
-
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.
-
REBUILD kolumnowego indeksu klastrowanego OFFLINE na SQL Server 2017 i starszych — tabela będzie całkowicie niedostępna nawet przy
NOLOCKczy 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.)
