Hash zagregowanego ratowania

10

Pytanie, które pojawiło się podczas dyskusji na czacie:

Wiem, że skróty łączą pakiety ratunkowe wewnętrznie do czegoś w rodzaju zagnieżdżonych pętli.

Co robi SQL Server dla ratowania agregacji skrótów (jeśli w ogóle może się to zdarzyć)?

Paul White 9
źródło

Odpowiedzi:

11

Łączenie skrótów i agregacja skrótów używają tego samego kodu operatora wewnętrznie, chociaż agregat skrótu używa tylko jednego wejścia (kompilacji). Podstawowa operacja mieszania kruszywa jest opisany przez Craig Freedman :

Podobnie jak w przypadku łączenia skrótu, agregat skrótu wymaga pamięci. Przed wykonaniem zapytania z agregacją skrótu SQL Server używa oszacowań liczności w celu oszacowania ilości pamięci potrzebnej do wykonania zapytania. W przypadku łączenia mieszającego przechowujemy każdy wiersz kompilacji, więc całkowite zapotrzebowanie na pamięć jest proporcjonalne do liczby i wielkości wierszy kompilacji. Liczba połączonych wierszy i wyjściowa liczność sprzężenia nie mają wpływu na wymaganą pamięć połączenia. Dzięki agregacji skrótów przechowujemy jeden wiersz dla każdej grupy, więc całkowite zapotrzebowanie na pamięć jest w rzeczywistości proporcjonalne do liczby i wielkości grup wyjściowych lub wierszy. Jeśli mamy mniej unikalnych wartości grupy według kolumn (kolumn) i mniej grup, potrzebujemy mniej pamięci. Jeśli mamy więcej unikalnych wartości grupy według kolumn i więcej grup, potrzebujemy więcej pamięci.

Następnie mówi o rekurencji skrótu:

Co się stanie, jeśli zabraknie nam pamięci? Ponownie, podobnie jak łączenie mieszające, jeśli zabraknie nam pamięci, musimy zacząć rozlewać wiersze do tempdb. Rozlewamy jeden lub więcej segmentów lub partycji, w tym wyniki częściowo zagregowane wraz z wszelkimi dodatkowymi nowymi wierszami łączącymi się z rozlanymi segmentami lub partycjami. Chociaż nie próbujemy agregować rozlanych nowych wierszy, robimy je mieszając i dzielimy na kilka segmentów lub partycji. Po zakończeniu przetwarzania wszystkich grup wejściowych wysyłamy gotowe grupy w pamięci i powtarzamy algorytm, odczytując i agregując jedną rozlaną partycję na raz. Dzieląc rozlane wiersze na wiele partycji, zmniejszamy rozmiar każdej partycji, a tym samym zmniejszamy ryzyko, że algorytm będzie musiał wiele razy powtarzać.

Bailout

Pakiet ratunkowy Hash jest lekko udokumentowany, ale wspomniany przez Nacho Alonso Portillo w Jaki jest maksymalny poziom rekurencji dla iteratora skrótu przed wymuszeniem ratowania?

Wartość jest stała, zakodowana na stałe w produkcie, a jej wartość wynosi pięć (5). Oznacza to, że zanim operator skanowania skrótu zastosuje algorytm oparty na sortowaniu dla dowolnej podsekcji, która nie mieści się w przyznanej pamięci z obszaru roboczego, musiało się zdarzyć pięć poprzednich prób podzielenia oryginalnej partycji na mniejsze partycje.

„Operator skanowania skrótu” wspomniał, że istnieje odniesienie do klasy wewnętrznej CQScanHashw sqlmin.dll. Ta klasa kieruje implementacją operatora skrótu (we wszystkich jego postaciach, w tym w częściowych agregatach i odrębnych przepływach), co widzimy w planach wykonania.

Algorytm ratowania

To prowadzi nas do sedna twoich pytań - co dokładnie robi algorytm ratowania? Czy jest to „oparte na sortowaniu” czy oparte na „rodzaju zagnieżdżonej pętli”?

Jest to prawdopodobnie jedno i drugie, w zależności od twojego punktu widzenia. Kiedy rekursja skrótu osiągnie poziom 5, partycja skrótu w pamięci zmienia się z tabeli skrótów w początkowo pusty indeks b-drzewa wartości skrótu. Każdy wiersz z jednej wcześniej rozlanej partycji mieszającej jest sprawdzany w indeksie b-drzewa i odpowiednio wstawiany (nowa grupa) lub aktualizowany (zachowując agregacje).

Ta seria nieuporządkowanych wstawek do b-drzewa może być równie dobrze postrzegana jako rodzaj wstawiania lub jako indeksowane wyszukiwanie zagnieżdżonych pętli.

W każdym razie gwarantuje się, że ten algorytm rezerwowy zostanie ostatecznie ukończony bez przydzielania większej ilości pamięci. Może to wymagać wielu przejść, jeśli przestrzeń dostępna dla b-drzewa nie jest wystarczająca do przechowywania wszystkich kluczy i agregatów grupowania z partycji przepełnienia.

Po wyczerpaniu pamięci dostępnej do przechowywania indeksu b-drzewa wszelkie dalsze wiersze (z bieżącej rozlanej partycji) są wysyłane do pojedynczej nowej partycji tempdb (która z pewnością jest mniejsza) i proces powtarza się w razie potrzeby. Poziom wycieku pozostaje na poziomie 5, ponieważ zakończyła się rekurencja mieszania . Niektóre szczegóły przetwarzania można zaobserwować za pomocą nieudokumentowanej flagi śledzenia 7357.

Paul White 9
źródło