Czy ALTER INDEX ALL REBUILD wykorzystuje więcej miejsca w dzienniku transakcji przy użyciu prostego modelu odzyskiwania niż odbudowywanie każdego indeksu indywidualnie?

18

Operacja „ALTER INDEX ALL REBUILD” na SQL Server 2012 nie powiodła się, ponieważ w dzienniku transakcji zabrakło miejsca. Indeksy nigdy nie zostały zreorganizowane ani odbudowane, więc fragmentacja wynosi ponad 80% na prawie wszystkich z nich.

Baza danych wykorzystuje prosty model odzyskiwania. Zakładałem, że po każdej operacji indeksu wykonywanej przez komendę „WSZYSTKO” dane dziennika transakcji zostaną wyczyszczone przed kolejną odbudową indeksu. Czy tak to faktycznie działa, czy też rejestruje się przebudowy indeksu tak, jakby były częścią pojedynczej transakcji?

Innymi słowy, czy mogę zmniejszyć wzrost dziennika transakcji, pisząc skrypt wykonujący każdą przebudowę indywidualnie? Czy są jeszcze inne czynniki do rozważenia?

Google Fail
źródło
2
Z wyjątkiem jawnych danych przeciwnych, zakładam, że określone polecenie SQL byłoby traktowane jako pojedyncza transakcja atomowa przez silnik DB. W takim przypadku możesz dość łatwo przetestować teorię. Weź swój największy indeks i spróbuj go odbudować. Jeśli to się powiedzie, uzasadnione jest założenie, że dziennik gromadzi informacje z wielu odbudowań. Jeśli to się nie powiedzie, musisz dodać miejsce na dziennik (ponieważ masz problem w obu kierunkach) lub musisz spróbować zreorganizować ten indeks zamiast odbudowywać (jeśli nie możesz zwiększyć miejsca dla t- log).
RDFozz
Tak, ta myśl przyszła mi do głowy, kiedy skończyłem pisać (efekt gumowej kaczki), ale pomyślałem, że najlepiej będzie uzyskać potwierdzenie i zostawić to innym, którzy mogą myśleć w ten sam sposób. Nie chcę eksperymentować z tym środowiskiem, więc prawdopodobnie i tak skończę dodając miejsce do dzienników.
Google Fail

Odpowiedzi:

16

Zakładałem, że po każdej operacji indeksu wykonywanej przez komendę „WSZYSTKO” dane dziennika transakcji zostaną wyczyszczone przed kolejną odbudową indeksu. Czy tak to faktycznie działa, czy też rejestruje się przebudowy indeksu tak, jakby były częścią pojedynczej transakcji?

1) Płukanie dziennika: model odzyskiwania SIMPLE nie usuwa dziennika po każdej transakcji, ale w punktach kontrolnych. ( link, aby uzyskać więcej informacji)

2a) ODBUDUJ WSZYSTKO: tak, ODBUDUJ WSZYSTKO działa jako pojedyncza transakcja. Indeks odbudowuje w ramach własnych transakcji, ale cała operacja nie jest w pełni zatwierdzona do końca. Tak, możesz ograniczyć wzrost pliku dziennika, odbudowując poszczególne indeksy (i ewentualnie wydając polecenia CHECKPOINT).

2b) Dowód! Tutaj masz skrypt demonstracyjny. (Wbudowane w 2016 dev) Najpierw skonfiguruj testową bazę danych z tabelą i indeksami:

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')

Teraz możesz porównać aktywność dziennika między REBUILD ALL a odbudowaniem indywidualnie

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

Zwróć uwagę, że pierwsza otwarta transakcja (dla mnie identyfikator transakcji 0000: 000002fa) nie jest zatwierdzana do końca ODBUDUJ WSZYSTKO, ale w przypadku przebudowań indeks po indeksie są one zatwierdzane sukcesywnie.

Forrest
źródło
Wow, dzięki za naprawdę szczegółową odpowiedź! To świetny sposób, aby zobaczyć, co się dzieje pod maską.
Google Fail
Ładnie wyjaśnione.
Ramakant Dadhichi
4

W obecnej formie jest to pojedyncza transakcja.

Pedro Lopes
źródło
6
Witamy w DBA.SE! Ogólnie rzecz biorąc, najlepsze odpowiedzi nie są prostymi stwierdzeniami, ale są poparte informacjami z dokumentacji lub artykułów lub (często jeszcze lepszym) osobistym doświadczeniem potwierdzającym podaną odpowiedź. Czy możesz rozwinąć swoją odpowiedź, aby zapewnić tego rodzaju wsparcie?
RDFozz
2
@RDFozz Uczciwy komentarz, ale czy spojrzałeś na profil Pedro ? Dostęp do kodu źródłowego można prawdopodobnie uznać za bardziej autorytatywny niż osobiste doświadczenie lub dokumentacja. :-)
Aaron Bertrand
3
@AaronBertrand - Przyznaję, że nie. Z pewnością pomyślałbym, że bycie częścią zespołu SQL Server naprawdę się kwalifikuje. Mimo to warto odnieść się do tego w odpowiedzi. +1, w każdym razie.
RDFozz
3

Pytanie jest trywialne w przypadku przebudowy offline . Oczywiście jest to pojedyncza transakcja. Wyobraź sobie spustoszenie, które nastąpiłoby, gdyby operacja podzieliła każdy indeks na własną transakcję, ponieważ musiałby zwolnić blokady podczas zatwierdzania, a następnie je odzyskać. Chociaż zwolniono blokadę tabeli krytycznej SCH-M, indeksy mogą być usuwane i można tworzyć nowe indeksy. W jaki sposób instrukcja obsługiwałaby takie przypadki? Nie wspominając o tym, że tabela może zostać usunięta, a nawet odtworzona między dwiema transakcjami! W tym przypadek upuszczenia tabeli i utworzenia innej tabeli o tym samym identyfikatorze obiektu (tak, może się zdarzyć) ...

Co jeśli wzmocnisz pytanie, aby powiedzieć, co się stanie, jeśli odbudowa indeksu jest przebudową online ? Czy to pojedyncza transakcja czy wiele? Odpowiedź jest złożona, ponieważ w rzeczywistości zaangażowanych jest kilka transakcji wewnętrznych . Jednak kluczową kwestią jest to, że istnieje ogólna transakcja archiwizacji obejmująca całą operację (instrukcja ALTER), co powoduje przypięcie dziennika do miejsca (nie można go obciąć), dlatego operacja musi zostać odpowiednio zaplanowana, aby umożliwić ~ 1,6x danych rozmiar dla trybu odzyskiwania FULL lub rozmiar danych 0,2x dla trybu BULK_LOGGED / SIMPLE. Więcej informacji na ten temat znajduje się w powiązanym dokumencie

Możesz argumentować, że dlaczego kompilacja offline nie wykorzystuje tych samych transakcji wewnętrznych co tryb online i nie podzieliła operacji? Problemy, o których wspominałem o zmianie / upuszczeniu tabeli między poszczególnymi operacjami indeksu (tj. „Stabilność schematu”) nadal wymagałyby obejmowania transakcji obejmującej SCH-S na stole przez cały czas trwania instrukcji. Ponieważ ta transakcja musi przechowywać SCH-S również podczas odzyskiwania, musi zostać zarejestrowana, i jako taki będzie rekord BEGIN XACT, który przypina dziennik i zapobiega obcięciu przez cały czas trwania instrukcji. Wiem, że ten konkretny problem został rozwiązany w ramach czasowych SQL 2016-2017 (z powodu problemów z rozmiarem dziennika SQL Azure), ale nie jestem pewien, jaki postęp został osiągnięty . Wygląda na to, że jest teraz w wersji zapoznawczej:Resumable Online Index Rebuild jest publicznie dostępny dla SQL Server 2017 CTP 2.0 .

Remus Rusanu
źródło
0

Tak, miałem ten sam problem z bardzo dużym stołem. Ilekroć wydawałem ALTER INDEX ALL, dziennik transakcji znacznie się rozwijał, ale jeśli wydawano by ALTER INDEX indywidualnie, użycie miejsca na dziennik byłoby mniejsze.

LT
źródło
0

Wcześniejsza odpowiedź Remusa, że ​​indeksowanie online wymaga 1,6-krotności rozmiaru indeksu w trybie PEŁNEGO odzyskiwania, jest nieprawidłowa. Odsetek miejsca do rejestrowania transakcji wymaganego do przebudowania indeksu online w trybie FULL może być znacznie wyższy i zaobserwowaliśmy wielokrotnie wielkość indeksu, szczególnie gdy kompilowany indeks jest kompresowany, ponieważ rejestrowanie transakcji nie jest kompresowane. Już samo to powinno wyjaśnić, że rejestrowanie transakcji podczas przebudowy online w trybie FULL może być co najmniej kilka razy większe niż indeks. Dodaj narzut rekordu tlog, który nie jest w pełni udokumentowany przez Microsoft, ale często jest szacowany na 60 bajtów na wiersz, a proporcjonalny rozmiar rejestrowania podczas przebudowywania indeksu online przy pełnym odzyskiwaniu może być wielokrotnie większy niż rozmiar przebudowywanego indeksu, szczególnie jeśli indeks jest skompresowany

Greg Linwood
źródło
-1

Rdfozz ma rację, to najlepszy sposób, aby zdecydować, czy Twój największy indeks można odbudować na podstawie bieżącej pamięci. Wystarczy uruchomić dm_exec_requestspodczas operacji (lub SQL Profiler), aby sprawdzić, czy wszystkie indeksy są przebudowywane. Zastanowiłbym się również nad zmianą modelu odzyskiwania na masowe logowanie. To właśnie robię i nadal istnieją kopie zapasowe dziennika transakcji w oknie. Zobacz poniższy artykuł https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx

ADTJOB
źródło
2
Należy zauważyć, że OP stwierdził, że ich DB używa już modelu odzyskiwania SIMPLE; dzięki temu transakcje są przechowywane w dzienniku wystarczająco długo, aby transakcje mogły zostać zakończone. Nie byłoby poprawy, gdyby zmieniono na masowe logowanie.
RDFozz
Masz rację. Przepraszam.
ADTJOB