Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy do:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
System Platform Analitycznych (PDW)
Baza danych SQL w Microsoft Fabric
Program SQL Server używa sprzężeń do pobierania danych z wielu tabel na podstawie relacji logicznych między nimi. Sprzężenia są fundamentalne dla operacji relacyjnej bazy danych i umożliwiają łączenie danych z co najmniej dwóch tabel w jeden zestaw wyników.
Program SQL Server implementuje operacje sprzężenia logicznego (zdefiniowane przez składnię Transact-SQL) i operacje sprzężenia fizycznego (rzeczywiste algorytmy używane do wykonywania sprzężeń). Zrozumienie obu aspektów ułatwia pisanie wydajnych zapytań i optymalizowanie wydajności bazy danych.
Operacje sprzężenia logicznego obejmują:
- Sprzężenia wewnętrzne
- Sprzężenia zewnętrzne od lewej, prawej i pełnej
- Sprzężenia krzyżowe
Operacje sprzężenia fizycznego obejmują:
- Połączenia zagnieżdżonych pętli
- Scalanie sprzężeń
- Sprzężenia skrótów
- Sprzężenia adaptacyjne (dotyczy: SQL Server 2017 (14.x) i nowsze wersje)
W tym artykule wyjaśniono, jak działają sprzężenia, kiedy należy używać różnych typów sprzężeń oraz jak optymalizator zapytań wybiera najbardziej wydajny algorytm sprzężenia na podstawie czynników, takich jak rozmiar tabeli, dostępne indeksy i dystrybucja danych.
Note
Aby uzyskać więcej informacji na temat składni sprzężenia, zobacz KLAUZULA FROM oraz JOIN, APPLY, PIVOT.
Podstawy dołączania
Za pomocą sprzężeń można pobrać dane z co najmniej dwóch tabel na podstawie relacji logicznych między tabelami. Sprzężenia wskazują, jak program SQL Server powinien używać danych z jednej tabeli do wybierania wierszy w innej tabeli.
Warunek sprzężenia definiuje sposób, w jaki dwie tabele są powiązane w zapytaniu przez:
- Określanie kolumny z każdej tabeli do wykorzystania przy sprzężeniu. Typowy warunek sprzężenia określa klucz obcy z jednej tabeli i skojarzony z nim klucz w drugiej tabeli.
- Określanie operatora logicznego (na przykład = lub <>, ), który ma być używany w porównywaniu wartości z kolumn.
Sprzężenia są wyrażane logicznie przy użyciu następującej składni Transact-SQL:
[ INNER ] JOINLEFT [ OUTER ] JOINRIGHT [ OUTER ] JOINFULL [ OUTER ] JOINCROSS JOIN
Sprzężenia wewnętrzne można określić w klauzulach FROM lub WHERE.
Sprzężenia zewnętrzne i sprzężenia krzyżowe można określić tylko w klauzuli FROM. Warunki sprzężenia łączą się z warunkami wyszukiwania WHERE i HAVING w celu kontrolowania wierszy wybranych z tabel bazowych, na które referuje klauzula FROM.
Określenie warunków sprzężenia w klauzuli FROM pomaga oddzielić je od innych warunków wyszukiwania, które mogą być określone w WHERE klauzuli, i jest zalecaną metodą określania sprzężeń. Uproszczona składnia łączenia klauzul ISO FROM to:
FROM first_table < join_type > second_table [ ON ( join_condition ) ]
- Join_type określa, jakiego rodzaju sprzężenie jest wykonywane: sprzężenie wewnętrzne, zewnętrzne lub krzyżowe. Aby uzyskać wyjaśnienia różnych typów sprzężeń, zobacz klauzulę FROM.
- Join_condition definiuje predykat, który ma być oceniany dla każdej pary sprzężonych wierszy.
Poniższy kod jest przykładem specyfikacji FROM łączenia klauzuli:
FROM Purchasing.ProductVendor INNER JOIN Purchasing.Vendor
ON ( ProductVendor.BusinessEntityID = Vendor.BusinessEntityID )
Poniższy kod jest prostą SELECT instrukcją używającą tego sprzężenia:
SELECT ProductID, Purchasing.Vendor.BusinessEntityID, Name
FROM Purchasing.ProductVendor INNER JOIN Purchasing.Vendor
ON (Purchasing.ProductVendor.BusinessEntityID = Purchasing.Vendor.BusinessEntityID)
WHERE StandardPrice > $10
AND Name LIKE N'F%';
GO
Instrukcja SELECT zwraca informacje o produkcie i dostawcy dla dowolnej kombinacji części dostarczonych przez firmę, dla której nazwa firmy zaczyna się od litery F, a cena produktu jest większa niż 10 USD.
Jeśli w jednym zapytaniu odwołuje się wiele tabel, wszystkie odwołania do kolumn muszą być jednoznaczne. W poprzednim przykładzie obie tabele ProductVendor i Vendor mają kolumnę o nazwie BusinessEntityID. Każda nazwa kolumny, która jest zduplikowana między co najmniej dwiema tabelami, do których odwołuje się kwerenda, musi być kwalifikowana przy użyciu nazwy tabeli. Wszystkie odwołania do Vendor kolumn w przykładzie są kwalifikowane.
Jeśli nazwa kolumny nie jest duplikowana w co najmniej dwóch tabelach używanych w zapytaniu, odwołania do niej nie muszą być kwalifikowane przy użyciu nazwy tabeli. Jest to pokazane w poprzednim przykładzie. Taka klauzula SELECT czasami jest trudna do zrozumienia, ponieważ nie ma nic do wskazania tabeli, która dostarczyła każdą kolumnę. Czytelność zapytania jest ulepszona, jeśli wszystkie kolumny są kwalifikowane przy użyciu ich nazw tabel. Czytelność jeszcze bardziej się poprawia, jeśli używane są aliasy tabel, zwłaszcza gdy nazwy tabel muszą być kwalifikowane jako nazwy bazy danych i właścicieli. Poniższy kod jest tym samym przykładem, z tą różnicą, że aliasy tabeli zostały przypisane, a kolumny kwalifikowane za pomocą aliasów tabeli w celu zwiększenia czytelności:
SELECT pv.ProductID, v.BusinessEntityID, v.Name
FROM Purchasing.ProductVendor AS pv
INNER JOIN Purchasing.Vendor AS v
ON (pv.BusinessEntityID = v.BusinessEntityID)
WHERE StandardPrice > $10
AND Name LIKE N'F%';
W poprzednich przykładach określono warunki sprzężenia w klauzuli FROM , która jest preferowaną metodą. Następujące zapytanie zawiera ten sam warunek sprzężenia określony w klauzuli WHERE :
SELECT pv.ProductID, v.BusinessEntityID, v.Name
FROM Purchasing.ProductVendor AS pv, Purchasing.Vendor AS v
WHERE pv.BusinessEntityID=v.BusinessEntityID
AND StandardPrice > $10
AND Name LIKE N'F%';
Lista SELECT sprzężenia może odwoływać się do wszystkich kolumn zawartych w sprzężonych tabelach lub dowolnego podzbioru kolumn. Lista nie jest wymagana SELECT do zawierania kolumn z każdej tabeli w sprzężeniu. Na przykład, w łączeniu trzech tabel tylko jedna tabela może pośredniczyć między jedną z pozostałych a trzecią tabelą, a żadna z kolumn z tabeli środkowej nie musi być przywoływana na liście SELECT. Jest to również nazywane sprzężeniem antyłącznym.
Chociaż warunki sprzężenia zwykle mają porównania równości (=), można określić operatory porównawcze lub relacyjne, podobnie jak inne predykaty. Aby uzyskać więcej informacji, zobacz Operatory porównania i GDZIE.
Kiedy SQL Server przetwarza operacje sprzężenia, optymalizator zapytań SQL Servera wybiera najbardziej wydajną metodę spośród kilku opcji przetwarzania sprzężenia. Obejmuje to wybór najbardziej wydajnego typu sprzężenia fizycznego, kolejność łączenia tabel, a nawet przy użyciu typów operacji sprzężenia logicznego, których nie można bezpośrednio wyrazić za pomocą składni Transact-SQL, takich jak sprzężenia częściowe i sprzężenia częściowe. Fizyczne wykonywanie różnych sprzężeń może korzystać z wielu różnych optymalizacji i dlatego nie można niezawodnie przewidzieć. Aby uzyskać więcej informacji na temat sprzężeń częściowych i sprzężeń antysemickich, zobacz Informacje o operatorach logicznych i fizycznych showplanach.
Kolumny używane w warunku sprzężenia nie są wymagane do posiadania tej samej nazwy lub tego samego typu danych. Jeśli jednak typy danych nie są identyczne, muszą być zgodne lub typy, które program SQL Server może niejawnie konwertować. Jeśli typy danych nie mogą być konwertowane niejawnie, warunek sprzężenia musi jawnie przekonwertować typ danych przy użyciu CAST funkcji . Aby uzyskać więcej informacji na temat niejawnych i jawnych konwersji, zobacz Konwersja typów danych (aparat bazy danych).
Większość zapytań używających sprzężenia może zostać przepisana przy użyciu podzapytania (zapytanie zagnieżdżone w ramach innego zapytania), a większość podzapytania może zostać przepisana jako sprzężenia. Aby uzyskać więcej informacji na temat podzapytania, zobacz Podzapytania (SQL Server).
Note
Tabele nie mogą być łączone bezpośrednio w kolumnach ntext, text lub image. Tabele można jednak łączyć pośrednio w kolumnach ntext, text lub image przy użyciu polecenia SUBSTRING.
Na przykład SELECT * FROM t1 JOIN t2 ON SUBSTRING(t1.textcolumn, 1, 20) = SUBSTRING(t2.textcolumn, 1, 20) wykonuje sprzężenie wewnętrzne z dwiema tabelami na pierwszych 20 znakach każdej kolumny tekstowej w tabelach t1 i t2.
Ponadto kolejną możliwością porównywania ntekstu lub kolumn tekstowych z dwóch tabel jest porównanie długości kolumn z klauzulą WHERE , na przykład: WHERE DATALENGTH(p1.pr_info) = DATALENGTH(p2.pr_info)
Zrozumienie sprzężeń zagnieżdżonych pętli
Jeśli jedno wejście sprzężenia jest małe (mniej niż 10 wierszy), a drugie wejście sprzężenia jest dość duże i indeksowane w kolumnach sprzężenia, sprzężenie zagnieżdżone przy użyciu indeksu jest najszybszą operacją sprzężenia, ponieważ wymaga najmniejszej liczby operacji we/wy i najmniejszej liczby porównań.
Złączenie zagnieżdżonych pętli, nazywane również iteracją zagnieżdżoną, wykorzystuje jedno wejście jako zewnętrzną tabelę wejściową (widoczną jako górne wejście w graficznym planie wykonawczym) i jedno jako wewnętrzną (dolną) tabelę wejściową. Pętla zewnętrzna przetwarza zewnętrzną tabelę wejściową wiersz po wierszu. Pętla wewnętrzna, wykonywana dla każdego wiersza zewnętrznego, wyszukuje pasujące wiersze w wewnętrznej tabeli wejściowej.
W najprostszym przypadku wyszukiwanie skanuje całą tabelę lub indeks; jest to nazywane naiwnym połączeniem zagnieżdżonych pętli. Jeśli wyszukiwanie wykorzystuje indeks, jest to nazywane sprzężeniami zagnieżdżonych indeksów. Jeśli indeks jest kompilowany jako część planu zapytania (i niszczony po zakończeniu zapytania), jest nazywany tymczasowym sprzężeniem zagnieżdżonych pętli indeksu. Wszystkie te warianty są brane pod uwagę przez Optymalizator zapytań.
Łączenie zagnieżdżonych pętli jest szczególnie skuteczne, jeśli zewnętrzne dane wejściowe są małe, a wewnętrzne dane wejściowe są wstępnie indeksowane i duże. W wielu małych transakcjach, takich jak te wpływające tylko na niewielki zestaw wierszy, łączenia z zagnieżdżonymi pętlami indeksu są lepsze zarówno od sprzężeń scalających, jak i sprzężeń skrótowych. Jednak w dużych zapytaniach sprzężenia zagnieżdżone często nie są optymalnym wyborem.
Gdy atrybut OPTIMIZED operatora sprzężenia zagnieżdżonego ma wartość True, oznacza to, że zoptymalizowane pętle zagnieżdżone (lub sortowanie wsadowe) są używane do minimalizacji operacji wejścia/wyjścia, gdy tabela wewnętrzna jest duża, bez względu na to, czy jest równoległa, czy nie. Obecność tej optymalizacji w danym planie może nie być bardzo oczywista podczas analizowania planu wykonania, biorąc pod uwagę, że samo sortowanie jest operacją niewidoczną. Jednak analizując kod XML planu w poszukiwaniu atrybutu OPTIMIZED, można zauważyć, że sprzężenie zagnieżdżonych pętli może próbować zmienić kolejność wierszy wejściowych, aby poprawić wydajność operacji we/wy.
Scalanie sprzężeń
Jeśli dwa sprzężenia wejściowe nie są małe, ale są sortowane w kolumnie sprzężenia (na przykład jeśli zostały uzyskane przez skanowanie posortowanych indeksów), sprzężenie scalania jest najszybszą operacją sprzężenia. Jeśli oba wejścia do sprzężenia są duże, a ich rozmiary są podobne, sprzężenie scalające z wcześniejszym sortowaniem oraz sprzężenie z wykorzystaniem tabeli skrótu oferują podobną wydajność. Jednak operacje sprzężenia skrótu są często znacznie szybsze, jeśli rozmiary dwóch wejść różnią się znacząco.
Sprzężenie scalania wymaga sortowania obu danych wejściowych w kolumnach scalania, które są definiowane przez klauzule równości (ON) predykatu sprzężenia. Optymalizator zapytań zwykle skanuje indeks, jeśli istnieje w przypadku odpowiedniego zestawu kolumn, lub umieszcza operator sortowania poniżej operatora scalania. W rzadkich przypadkach może istnieć wiele klauzul równości, ale kolumny scalania są pobierane tylko z niektórych dostępnych klauzul równości.
Ponieważ każde dane wejściowe są sortowane, operator Scal sprzężenia pobiera wiersz z każdego danych wejściowych i porównuje je. Na przykład w przypadku operacji sprzężenia wewnętrznego wiersze są zwracane, jeśli są równe. Jeśli nie są równe, wiersz niższej wartości zostanie odrzucony, a inny wiersz zostanie uzyskany z tych danych wejściowych. Proces ten powtarza się aż do momentu przetworzenia wszystkich wierszy.
Operacja łączenia jest operacją regularną lub wiele do wielu. Łączenie scalające wiele do wielu używa tabeli tymczasowej do przechowywania wierszy. Jeśli istnieją zduplikowane wartości z każdego wejścia, jedno z wejść musi się przewinąć na początek duplikatów, gdy każdy duplikat z innego wejścia jest przetwarzany.
Jeśli predykat reszt jest obecny, wszystkie wiersze spełniające predykat scalania obliczają predykat reszt i zwracane są tylko te wiersze, które je spełniają.
Samo sprzężenia scalania są bardzo szybkie, ale może to być kosztowny wybór, jeśli wymagane są operacje sortowania. Jeśli jednak objętość danych jest duża, a żądane dane można uzyskać wstępnie posortowane z istniejących indeksów B-drzewa, łączenie przez scalanie jest często najszybszym dostępnym algorytmem łączenia.
Sprzężenia skrótów
Sprzężenia skrótów mogą efektywnie przetwarzać duże, niesortowane, nieindeksowane dane wejściowe. Są one przydatne w przypadku wyników pośrednich w złożonych zapytaniach, ponieważ:
- Wyniki pośrednie nie są indeksowane (chyba że jawnie zapisane na dysku, a następnie indeksowane) i często nie są odpowiednio sortowane dla następnej operacji w planie zapytania.
- Optymalizatory zapytań szacują tylko pośrednie rozmiary wyników. Ponieważ szacunki mogą być bardzo niedokładne w przypadku złożonych zapytań, algorytmy przetwarzania wyników pośrednich nie tylko muszą być wydajne, ale także muszą bezpiecznie obniżyć wydajność, jeśli wynik pośredni okaże się znacznie większy niż oczekiwano.
Operacja "hash join" pozwala na zmniejszenie potrzeby używania denormalizacji. Denormalizacja jest zwykle używana do osiągnięcia lepszej wydajności przez zmniejszenie operacji łączenia, pomimo niebezpieczeństw związanych z redundancją, takich jak niespójne aktualizacje. Łączenia mieszające zmniejszają potrzebę denormalizacji. Sprzężenia skrótu umożliwiają partycjonowanie pionowe (które reprezentuje grupy kolumn z pojedynczej tabeli w osobnych plikach lub indeksach), aby stało się realną opcją projektowania fizycznej bazy danych.
Połączenie skrótu ma dwa dane wejściowe: dane wejściowe budowania i dane wejściowe sondy. Optymalizator zapytań przypisuje te role, tak aby mniejsze z dwóch danych wejściowych było danymi wejściowymi kompilacji.
Łączenia skrótu są używane w przypadku wielu typów operacji dopasowywania zestawów: sprzężenia wewnętrznego, lewe, prawe i pełne sprzężenia zewnętrzne; lewe i prawe półsprzężenia; część wspólna; suma; i różnica. Ponadto wariant sprzężenia skrótu może wykonywać usuwanie duplikatów i grupowanie, takie jak SUM(salary) GROUP BY department. Te modyfikacje używają tylko jednego danych wejściowych zarówno dla ról kompilacji, jak i sondy.
W poniższych sekcjach opisano różne typy sprzężeń hashowych: sprzężenie hashowe w pamięci, sprzężenie grace hashowe i sprzężenie rekurencyjne hashowe.
Łączenie skrótu w pamięci
Funkcja sprzężenia skrótu najpierw skanuje lub oblicza całe dane wejściowe kompilacji, a następnie tworzy tabelę skrótów w pamięci. Każdy wiersz jest wstawiany do zasobnika skrótu w zależności od wartości skrótu obliczonej dla klucza skrótu. Jeśli całe dane wejściowe kompilacji są mniejsze niż dostępna pamięć, wszystkie wiersze można wstawić do tabeli skrótów. Po fazie kompilacji następuje faza sondy. Całe dane wejściowe sondy są skanowane lub obliczane jeden wiersz jednocześnie, a dla każdego wiersza sondy wartość klucza skrótu jest obliczana, odpowiedni zasobnik skrótu jest skanowany, a dopasowania są generowane.
Sprzężenie Grace hash join
Jeśli dane wejściowe kompilacji nie mieszczą się w pamięci, sprzężenia skrótu będą kontynuowane w kilku krokach. To jest znane jako łączenie haszujące typu grace. Każdy krok ma fazę kompilacji i fazę sondy. Początkowo całe dane wejściowe związane z kompilacją i sondowaniem są pobierane i dzielone na partycje za pomocą funkcji haszującej na kluczach haszujących na wiele plików. Użycie funkcji skrótu w kluczach skrótu gwarantuje, że wszystkie dwa rekordy łączenia muszą znajdować się w tej samej parze plików. W związku z tym zadanie łączenia dwóch dużych danych wejściowych zostało zredukowane do wielu, ale mniejszych wystąpień tych samych zadań. Łączenie przy użyciu funkcji skrótu jest następnie stosowane do każdej pary partycjonowanych plików.
Rekursywne łączenie skrótu
Jeśli dane wejściowe kompilacji są tak duże, że dane wejściowe dla standardowego scalania zewnętrznego wymagają wielu poziomów scalania, wymagane są wiele kroków partycjonowania i wiele poziomów partycjonowania. Jeśli tylko niektóre partycje są duże, dodatkowe kroki partycjonowania są używane tylko dla tych określonych partycji. Aby umożliwić jak najszybsze wykonanie wszystkich kroków partycjonowania, duże, asynchroniczne operacje we/wy są używane tak, aby jeden wątek mógł zachować wiele dysków zajętych.
Note
Jeśli dane wejściowe kompilacji są tylko nieco większe niż dostępna pamięć, elementy sprzężenia skrótu w pamięci i algorytmu sprzężenia skrótu typu grace są łączone w jednym kroku, tworząc hybrydowe sprzężenie skrótu.
Podczas optymalizacji nie zawsze jest możliwe określenie, które sprzężenie skrótu jest używane. W związku z tym program SQL Server zaczyna od użycia hash join w pamięci i stopniowo przechodzi do hash join typu grace oraz rekursywnego hash join, w zależności od rozmiaru danych wejściowych budowy.
Jeśli optymalizator zapytań przewiduje błędnie, które z dwóch danych wejściowych jest mniejsze i dlatego powinny być danymi wejściowymi kompilacji, role kompilacji i sondy są odwracane dynamicznie. Sprzężenie skrótu zapewnia, że używa mniejszego pliku przepełnienia jako danych wejściowych kompilacji. Ta technika jest nazywana odwróceniem roli. Odwrócenie roli występuje wewnątrz łączenia skrótu po co najmniej jednym zrzuceniu na dysk.
Note
Odwrócenie ról zachodzi niezależnie od wszelkich podpowiedzi zapytania czy struktury danych. Odwrócenie roli nie jest wyświetlane w planie zapytania; gdy wystąpi, jest on niewidoczny dla użytkownika.
Ratowanie skrótu
Termin ratowania skrótu jest czasami używany do opisywania sprzężeń skrótu grace lub cyklicznych sprzężeń skrótu.
Note
Rekursywne sprzężenia skrótów lub ratowania skrótów powodują zmniejszenie wydajności serwera. Jeśli w śladzie jest wyświetlanych wiele zdarzeń ostrzegawczych Hash, zaktualizuj statystyki dotyczące kolumn, które są łączone.
Aby uzyskać więcej informacji na temat ratowania skrótów, zobacz Hash Warning Event Class (Klasa zdarzenia ostrzeżenia skrótu).
Sprzężenia adaptacyjne
Tryb wsadowy Adaptacyjne sprzężenia umożliwiają odroczenie wyboru metody sprzężenia skrótu lub sprzężenia zagnieżdżonego do czasu, gdy pierwsze dane wejściowe zostały zeskanowane. Operator Sprzężenia Adaptacyjnego definiuje próg, który określa moment przełączenia się na plan zagnieżdżonych pętli. W związku z tym plan zapytania może dynamicznie przełączyć się na lepszą strategię łączenia podczas wykonywania bez konieczności ponownego kompilowania.
Tip
Obciążenia z częstymi oscylacjami między małymi i dużymi skanami wejściowymi łączenia najbardziej skorzystają z tej funkcji.
Decyzja środowiska uruchomieniowego jest oparta na następujących krokach:
- Jeśli liczba wierszy wejściowych sprzężenia kompilacji jest wystarczająco mała, że sprzężenie zagnieżdżonych pętli byłoby bardziej optymalne niż sprzężenie skrótu, plan przełącza się na algorytm zagnieżdżonych pętli.
- Jeśli dane wejściowe sprzężenia budowane przekraczają określony próg liczby wierszy, nie następuje przełączenie, a plan będzie kontynuowany przy użyciu sprzężenia haszującego.
Następujące zapytanie służy do zilustrowania przykładu sprzężenia adaptacyjnego.
SELECT [fo].[Order Key], [si].[Lead Time Days], [fo].[Quantity]
FROM [Fact].[Order] AS [fo]
INNER JOIN [Dimension].[Stock Item] AS [si]
ON [fo].[Stock Item Key] = [si].[Stock Item Key]
WHERE [fo].[Quantity] = 360;
Zapytanie zwraca 336 wierszy. Włączenie statystyk zapytań na żywo wyświetla następujący plan:
W planie zwróć uwagę na następujące kwestie:
- Skan indeksu magazynu kolumn używany do udostępniania wierszy dla fazy budowania sprzężenia haszującego.
- Nowy operator sprzężenia adaptacyjnego. Ten operator definiuje próg, który służy do decyzji, kiedy przełączyć się na stosowanie planu zagnieżdżonych pętli. W tym przykładzie próg wynosi 78 wierszy. Wszystkie elementy z >= 78 wierszy będą używać sprzężenia skrótu. Jeśli wartość mniejsza niż próg, zostanie użyte sprzężenia zagnieżdżone.
- Ponieważ zapytanie zwraca 336 wierszy, przekroczyło to próg, a więc druga gałąź reprezentuje fazę sondy standardowej operacji sprzężenia skrótu. Statystyki zapytań na żywo pokazują liczbę wierszy przepływających przez operatory — w tym przypadku „672 z 672”.
- Ostatnią gałęzią jest wyszukiwanie indeksu klastrowanego do użycia w sprzężeniu zagnieżdżonych pętli, gdyby próg nie został przekroczony. Zostaną wyświetlone wiersze "0 z 336" (gałąź jest nieużywane).
Teraz porównaj plan z tym samym zapytaniem, ale jeśli Quantity wartość ma tylko jeden wiersz w tabeli:
SELECT [fo].[Order Key], [si].[Lead Time Days], [fo].[Quantity]
FROM [Fact].[Order] AS [fo]
INNER JOIN [Dimension].[Stock Item] AS [si]
ON [fo].[Stock Item Key] = [si].[Stock Item Key]
WHERE [fo].[Quantity] = 361;
Zapytanie zwraca jeden wiersz. Włączenie statystyk zapytań na żywo wyświetla następujący plan:
W planie zwróć uwagę na następujące kwestie:
- Po zwróceniu jednego wiersza funkcja Wyszukiwania indeksu klastrowanego ma teraz przepływające wiersze.
- Ponieważ faza kompilacji sprzężenia skrótu nie została kontynuowana, nie ma wierszy przepływających przez drugą gałąź.
Uwagi dotyczące adaptacyjnego sprzężenia
Sprzężenia adaptacyjne wymagają więcej pamięci niż równoważny plan sprzężenia zagnieżdżonego pętli z indeksowaniem. Żądana jest dodatkowa pamięć, tak jakby zagnieżdżone pętle były wykorzystane jak Hash join. Istnieje również obciążenie dla fazy kompilacji jako operacji zatrzymania i przejścia w porównaniu z zagnieżdżonym sprzężeniami równoważnymi przesyłania strumieniowego pętli. Dzięki dodatkowym kosztom zapewniana jest elastyczność w scenariuszach, w których liczba wierszy waha się w danych wejściowych kompilacji.
Sprzężenia adaptacyjne trybu wsadowego działają na potrzeby początkowego wykonywania instrukcji, a po skompilowaniu kolejne wykonania pozostaną adaptacyjne na podstawie skompilowanego progu sprzężenia adaptacyjnego i wierszy środowiska uruchomieniowego przepływających przez fazę kompilacji danych wejściowych zewnętrznych.
Jeśli sprzężenie adaptacyjne przełączy się na operację zagnieżdżonych pętli, używa wierszy już odczytanych przez etap budowy sprzężenia skrótu. Operator nie odczytuje ponownie zewnętrznych wierszy odwołań.
Śledzenie działania adaptacyjnego sprzężenia
Operator adaptacyjnego sprzężenia ma następujące atrybuty operatora planu:
| Atrybut planu | Description |
|---|---|
| AdaptiveThresholdRows | Próg użycia do przełączania ze sprzężenia haszującego na łączenie zagnieżdżonej pętli. |
| EstimatedJoinType | Jaki prawdopodobny będzie typ sprzężenia. |
| ActualJoinType | W rzeczywistym planie został pokazany, jaki algorytm łączenia został ostatecznie wybrany na podstawie progu. |
Szacowany plan przedstawia kształt planu sprzężenia adaptacyjnego wraz ze zdefiniowanym progiem sprzężenia adaptacyjnego i szacowanym typem sprzężenia.
Tip
Query Store przechwytuje i może wymusić plan adaptacyjnego złączenia w trybie wsadowym.
Zapytania kwalifikujące się do przyłączenia adaptacyjnego
Kilka warunków sprawia, że sprzężenie logiczne kwalifikuje się do adaptacyjnego sprzężenia w trybie wsadowym.
- Poziom zgodności bazy danych wynosi 140 lub więcej.
- Zapytanie jest instrukcją
SELECT(instrukcje modyfikacji danych są obecnie niekwalifikowane). - Sprzężenie może być wykonane zarówno za pomocą zindeksowanego sprzężenia pętli zagnieżdżonych, jak i algorytmu fizycznego sprzężenia poprzez haszowanie.
- Sprzężenie skrótu używa trybu Batch, który jest aktywowany przez obecność indeksu columnstore w całym zapytaniu, przez tabelę z indeksowanym magazynem kolumn, do której sprzężenie się bezpośrednio odnosi, lub za pomocą trybu Batch w magazynie wierszy.
- Wygenerowane alternatywne strategie łączenia zagnieżdżonych pętli i łączenia haszującego powinny mieć to samo pierwsze dziecko (odniesienie zewnętrzne).
Wiersze progowe adaptacyjne
Na poniższym wykresie przedstawiono przykład przecięcia między kosztem sprzężenia Hash a kosztem sprzężenia z użyciem zagnieżdżonych pętli. W tym punkcie przecięcia określa się próg, który z kolei determinuje rzeczywisty algorytm używany do operacji sprzęgania.
Wyłączanie sprzężeń adaptacyjnych bez zmiany poziomu zgodności
Sprzężenia adaptacyjne można wyłączyć w zakresie bazy danych lub instrukcji, zachowując zgodność bazy danych na poziomie 140 i wyższym.
Aby wyłączyć sprzężenia adaptacyjne dla wszystkich wykonań zapytań pochodzących z bazy danych, wykonaj następujące czynności w kontekście odpowiedniej bazy danych:
-- SQL Server 2017
ALTER DATABASE SCOPED CONFIGURATION SET DISABLE_BATCH_MODE_ADAPTIVE_JOINS = ON;
-- Azure SQL Database, SQL Server 2019 and later versions
ALTER DATABASE SCOPED CONFIGURATION SET BATCH_MODE_ADAPTIVE_JOINS = OFF;
Po włączeniu to ustawienie jest wyświetlane jako włączone w sys.database_scoped_configurations.
Aby ponownie włączyć sprzężenia adaptacyjne dla wszystkich wykonań zapytań pochodzących z bazy danych, wykonaj następujące czynności w kontekście odpowiedniej bazy danych:
-- SQL Server 2017
ALTER DATABASE SCOPED CONFIGURATION SET DISABLE_BATCH_MODE_ADAPTIVE_JOINS = OFF;
-- Azure SQL Database, SQL Server 2019 and later versions
ALTER DATABASE SCOPED CONFIGURATION SET BATCH_MODE_ADAPTIVE_JOINS = ON;
Sprzężenia adaptacyjne można również wyłączyć dla określonego zapytania, określając DISABLE_BATCH_MODE_ADAPTIVE_JOINS jako wskazówkę zapytania USE HINT. Przykład:
SELECT s.CustomerID,
s.CustomerName,
sc.CustomerCategoryName
FROM Sales.Customers AS s
LEFT OUTER JOIN Sales.CustomerCategories AS sc
ON s.CustomerCategoryID = sc.CustomerCategoryID
OPTION (USE HINT('DISABLE_BATCH_MODE_ADAPTIVE_JOINS'));
Note
USE HINT Wskazówka zapytania ma pierwszeństwo przed ustawieniem konfiguracji w zakresie bazy danych lub flagi śledzenia.
Wartości null i sprzężenia
Jeśli w kolumnach połączonych tabel istnieją wartości null, wartości null nie są ze sobą zgodne. Obecność wartości null w kolumnie jednej z tabel będących w sprzężeniu może być zwracana tylko przy użyciu sprzężenia zewnętrznego (chyba że klauzula WHERE wyklucza wartości null).
Poniżej przedstawiono dwie tabele, które mają NULL w kolumnie, która będzie uczestniczyć w łączeniu.
table1 table2
a b c d
------- ------ ------- ------
1 one NULL two
NULL three 4 four
4 join4
Sprzężenia, które porównuje wartości w kolumnie a z kolumną c , nie uzyskuje dopasowania w kolumnach, które mają wartości NULL:
SELECT *
FROM table1 t1 JOIN table2 t2
ON t1.a = t2.c
ORDER BY t1.a;
GO
Zwracany jest tylko jeden wiersz z wartością 4 w kolumnach ac :
a b c d
----------- ------ ----------- ------
4 join4 4 four
(1 row(s) affected)
Wartości null zwracane z tabeli podstawowej są również trudne do odróżnienia od wartości null zwracanych z sprzężenia zewnętrznego. Na przykład następująca SELECT instrukcja wykonuje lewe sprzężenia zewnętrzne na tych dwóch tabelach:
SELECT *
FROM table1 t1 LEFT OUTER JOIN table2 t2
ON t1.a = t2.c
ORDER BY t1.a;
GO
Oto zestaw wyników.
a b c d
----------- ------ ----------- ------
NULL three NULL NULL
1 one NULL NULL
4 join4 4 four
(3 row(s) affected)
Wyniki nie ułatwiają odróżnienia NULL danych od elementu reprezentującego NULL błąd sprzężenia. Gdy NULL wartości są obecne w danych sprzężonych, zwykle zaleca się pominięcie ich z wyników przy użyciu zwykłego sprzężenia.