Dlaczego operator równoległości (strumieni podziału) zredukowałby szacunki rzędu do 1?

12

Korzystam z programu SQL Server 2012 Enterprise. Natknąłem się na plan SQL, który wykazuje pewne zachowania, których nie uważam za całkowicie intuicyjne. Po ciężkiej operacji Parallel Index Scan dochodzi do operacji Parallelism (Repartition Streams), ale zabija oszacowania wierszy zwracane przez skanowanie indeksu (Object10.Index2), zmniejszając oszacowanie do 1. Przeprowadziłem pewne wyszukiwanie, ale nie spotkałem niczego, co tłumaczy to zachowanie. Zapytanie jest dość proste, chociaż każda z tabel zawiera rekordy w niskich milionach. Jest to część procesu ładowania DWH i ten pośredni zestaw danych jest dotykany kilka razy przez cały czas, ale moje pytanie dotyczy w szczególności oszacowań wierszy. Czy ktoś może wyjaśnić, dlaczego dokładne oszacowania wiersza idą do 1 w operatorze równoległości (repartycji)? Również,

Opublikowałem pełny plan, aby wkleić plan .

Oto operacja, o której mowa:

wprowadź opis zdjęcia tutaj

Dołączanie drzewa planu w przypadku, gdy dodaje on więcej kontekstu:

wprowadź opis zdjęcia tutaj

Czy mogę napotkać jakąś odmianę tego elementu Connect złożonego przez Paula White'a (dalsze szczegółowe wyjaśnienia na jego blogu tutaj )? Przynajmniej jest to jedyna rzecz, którą znalazłem, która wydaje się być nawet w niewielkim stopniu zbliżona do tego, na co wpadam, mimo że w grze nie ma operatora TOP.

John Eisbrener
źródło

Odpowiedzi:

9

Plany zapytań z filtrami bitmapowymi mogą być czasami trudne do odczytania. Z artykułu BOL dotyczącego strumieni podziału (wyróżnienie moje):

Operator strumieni partycji zużywa wiele strumieni i tworzy wiele strumieni rekordów. Zawartość i format rekordu nie ulegają zmianie. Jeśli optymalizator zapytań korzysta z filtra bitmapowego, liczba wierszy w strumieniu wyjściowym jest zmniejszona.

Ponadto pomocny jest także artykuł na temat filtrów bitmapowych:

Analizując plan wykonania zawierający filtrowanie bitmap, ważne jest zrozumienie, w jaki sposób dane przepływają przez plan i gdzie stosowane jest filtrowanie. Filtr bitmapy i zoptymalizowana mapa bitowa są tworzone po stronie kompilacji (tabela wymiarów) sprzężenia mieszającego; jednak faktyczne filtrowanie jest zwykle wykonywane w operatorze Parallelism, który znajduje się po stronie wejściowej sondy (tabela faktów) sprzężenia mieszającego. Jednak gdy filtr bitmapowy oparty jest na kolumnie z liczbą całkowitą, filtr można zastosować bezpośrednio do początkowej operacji skanowania tabeli lub indeksu zamiast operatora Parallelism. Ta technika nazywa się optymalizacją rzędową.

Wierzę, że to właśnie obserwujesz w swoim zapytaniu. Możliwe jest stworzenie stosunkowo prostej wersji demonstracyjnej, która pokazuje operator strumieni partycjonowania zmniejszający oszacowanie liczności, nawet gdy operator bitmapy jest IN_ROWprzeciwny tabeli faktów. Przygotowanie danych:

create table outer_tbl (ID BIGINT NOT NULL);

INSERT INTO outer_tbl WITH (TABLOCK)
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values;

create table inner_tbl_1 (ID BIGINT NULL);
create table inner_tbl_2 (ID BIGINT NULL);

INSERT INTO inner_tbl_1 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

INSERT INTO inner_tbl_2 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Oto zapytanie, którego nie powinieneś uruchamiać:

SELECT *
FROM outer_tbl o
INNER JOIN inner_tbl_1 i ON o.ID = i.ID
INNER JOIN inner_tbl_2 i2 ON o.ID = i2.ID
OPTION (HASH JOIN, QUERYTRACEON 9481, QUERYTRACEON 8649);

Przesłałem plan . Spójrz na operatora w pobliżu inner_tbl_2:

podział przegranych wierszy

Pomocny może być również drugi test w Hash Joins on Nullable Columns autorstwa Paula White'a.

Istnieją pewne niespójności w sposobie stosowania redukcji wierszy. Widziałem to tylko w planie z co najmniej trzema stołami. Jednak zmniejszenie oczekiwanych wierszy wydaje się rozsądne przy właściwym rozmieszczeniu danych. Załóżmy, że połączona kolumna w tabeli faktów ma wiele powtarzanych wartości, które nie są obecne w tabeli wymiarów. Filtr bitmapowy może wyeliminować te wiersze, zanim dotrą do złączenia. W przypadku zapytania oszacowanie zostało zredukowane do 1. Sposób rozmieszczenia wierszy w funkcji skrótu stanowi dobrą wskazówkę:

dystrybucja wierszy

Na tej podstawie podejrzewam, że masz wiele powtarzających się wartości dla Object1.Column21kolumny. Jeśli powtarzające się kolumny nie znajdą się w histogramie statystyk, Object4.Column19wówczas SQL Server może bardzo źle oszacować liczność.

Myślę, że powinieneś się martwić, że poprawienie wydajności zapytania może być możliwe. Oczywiście, jeśli zapytanie spełnia wymagania dotyczące czasu odpowiedzi lub SLA, dalsze badanie może nie być warte. Jeśli jednak chcesz dokładniej zbadać sprawę, możesz zrobić kilka rzeczy (oprócz aktualizacji statystyk), aby dowiedzieć się, czy optymalizator zapytań wybrałby lepszy plan, gdyby miał lepsze informacje. Można umieścić Wyniki dołączyć pomiędzy Database1.Schema1.Object10i Database1.Schema1.Object11do tabeli temp i zobacz, czy nadal się pętla zagnieżdżona łączy. Możesz zmienić to połączenie na LEFT OUTER JOINtak, aby optymalizator zapytań nie zmniejszył liczby wierszy na tym etapie. Możesz dodać MAXDOP 1podpowiedź do swojego zapytania, aby zobaczyć, co się stanie. Możesz użyćTOPwraz z tabelą pochodną, ​​aby wymusić przejście do końca jako ostatnie, lub możesz nawet skomentować sprzężenie z zapytania. Mamy nadzieję, że te sugestie wystarczą, aby zacząć.

Jeśli chodzi o element Connect w pytaniu, jest bardzo mało prawdopodobne, że jest on powiązany z Twoim pytaniem. Ten problem nie dotyczy słabych oszacowań wierszy. Ma to związek z równoległym warunkiem wyścigu, który powoduje przetwarzanie zbyt wielu wierszy w planie zapytań za kulisami. Wygląda na to, że zapytanie nie wykonuje dodatkowej pracy.

Joe Obbish
źródło
6

Podstawowym problemem tutaj jest słaba ocena liczności dla wyniku pierwszego złączenia. Może to wynikać z wielu powodów, ale najczęściej są to nieaktualne statystyki lub szereg skorelowanych predykatów łączenia, które domyślny model optymalizatora są niezależne.

W tym drugim przypadku POPRAWKA: Niska wydajność po uruchomieniu zapytania zawierającego skorelowane ORAZ predykaty w SQL Server 2008 lub SQL Server 2008 R2 lub SQL Server 2012 może być istotna przy użyciu obsługiwanej flagi śledzenia 4137. Możesz również spróbować wykonać zapytanie z flaga śledzenia 4199, aby włączyć poprawki optymalizatora i / lub 2301, aby włączyć rozszerzenia modelowania. Trudno to ustalić na podstawie anonimowego planu.

Obecność mapy bitowej nie wpływa bezpośrednio na oszacowanie liczności sprzężenia, ale powoduje, że jej efekt jest widoczny wcześniej dzięki zastosowaniu wczesnej redukcji półjoinów. Bez mapy bitowej oszacowanie liczności dla pierwszego sprzężenia byłoby takie samo, a pozostała część planu nadal byłaby odpowiednio zoptymalizowana.

Jeśli jesteś ciekawy, w systemie testowym możesz wyłączyć mapy bitowe dla zapytania za pomocą flagi śledzenia 7498. Możesz również wyłączyć zoptymalizowane mapy bitowe (rozpatrywane przez optymalizator i wpływające na oszacowania liczności), zastępując je bitmapami po optymalizacji (nieuwzględnione przez optymalizator, bez wpływu na liczność) z kombinacją flag śledzenia 7497 i 7498. Ani nie jest udokumentowany ani obsługiwany do użycia w systemie produkcyjnym, ale opracowują plany, które optymalizator mógłby wziąć pod uwagę normalnie i dlatego można je wymusić przewodnik po planach.

Nic z tego nie rozwiąże podstawowego problemu złej prognozy dla pierwszego przyłączenia, jak wspomniano powyżej, więc tak naprawdę wspominam o tym ze względu na interesy.

Dalsza lektura bitmap i złączeń mieszających:

Paul White 9
źródło
0

odpowiedział na ciebie na Twitterze. Spojrzałem na załączony XML i dostrzegłem niezrównoważoną równoległość. 1 wątek ma prawie wszystkie rzeczywiste wiersze, podczas gdy większość innych nie. To krzyczy, że występuje niezrównoważona równoległość. Dlatego przyjrzałbym się wartości klucza / złączenia oraz jego statystykom i liczności.

Zgodnie z innym pomysłem nie jestem pewien, czy element Connect ma zastosowanie, ponieważ Twój wklejony plan nie zawiera TOP, gdziekolwiek widziałem.

SQLBek
źródło