Fizyczne działanie konkatenacji: czy gwarantuje kolejność wykonania?

12

W standardowym języku SQL wynik a union allnie jest gwarantowany w żadnej kolejności. Coś w stylu:

select 'A' as c union all select 'B'

Może zwrócić dwa wiersze w dowolnej kolejności (chociaż w praktyce w dowolnej znanej mi bazie danych „A” pojawi się przed „B”).

W SQL Server zamienia się to w plan wykonania przy użyciu operacji fizycznej „konkatenacji”.

Mogłem łatwo wyobrazić sobie, że operacja konkatenacji skanuje dane wejściowe, zwracając wszystko, co ma dostępne rekordy. Znalazłem jednak następujące oświadczenie w sieci ( tutaj ):

Procesor zapytań wykona ten plan w kolejności, w której operatorzy pojawią się w planie, pierwszy to najwyższy, a ostatni to ostatni.

Pytanie: Czy to prawda w praktyce? Czy to prawda, że ​​to prawda?

W dokumentacji Microsoft nie znalazłem żadnego odniesienia, że ​​dane wejściowe są skanowane w kolejności od pierwszego do ostatniego. Z drugiej strony, za każdym razem, gdy próbuję go uruchomić, wyniki sugerują, że dane wejściowe są w rzeczywistości przetwarzane w kolejności.

Czy istnieje sposób, aby silnik przetwarzał więcej niż jeden wkład na raz? Moje testy (wykorzystujące znacznie bardziej skomplikowane wyrażenia niż stałe) są na 8-rdzeniowej maszynie z równoległą obsługą, a większość zapytań korzysta z równoległości.

Gordon Linoff
źródło

Odpowiedzi:

10

Nie , nie ma dokumentacji od Microsoft gwarantującej zachowanie, dlatego nie jest gwarantowana .

Dodatkowo, zakładając, że artykuł Simple Talk jest poprawny i że fizyczny operator konkatenacji zawsze przetwarza dane wejściowe w kolejności pokazanej w planie (najprawdopodobniej będzie to prawda), to bez gwarancji, że SQL Server zawsze wygeneruje plany, które zachowają to samo kolejność między tekstem zapytania a planem zapytań, tylko nieznacznie lepiej.

Możemy to jednak zbadać dalej. Jeśli optymalizator kwerend był w stanie zmienić kolejność danych wejściowych operatora konkatenacji, w nieudokumentowanym DMV powinny istnieć wiersze sys.dm_exec_query_transformation_statsodpowiadające tej optymalizacji.

SELECT * FROM sys.dm_exec_query_transformation_stats 
    WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

W SQL Server 2012 Enterprise Edition daje to 24 wiersze. Ignorując fałszywe dopasowania dla transformacji związanych ze stałymi, istnieje jedna transformacja związana z fizycznym operatorem konkatenacji UNIAtoCON(suma wszystkich konkatenacji). Tak więc na poziomie operatora fizycznego wydaje się, że po wybraniu operatora konkatenacji zostanie on przetworzony w kolejności logicznego operatora Union All, z którego został uzyskany.


W rzeczywistości nie jest to do końca prawda. Istnieją zapisy po optymalizacji, które mogą zmienić kolejność danych wejściowych do fizycznego operatora konkatenacji po zakończeniu optymalizacji opartej na kosztach. Jeden przykład występuje, gdy konkatenacja podlega celowi rzędu (więc może być ważne, aby najpierw przeczytać tańsze dane wejściowe). Zobacz UNION ALLOptymalizacja autorstwa Paula White'a po więcej szczegółów.

Ta późna fizyczna przeróbka działała aż do SQL Server 2008 R2 włącznie, ale regresja oznaczała, że ​​nie była już stosowana w SQL Server 2012 i późniejszych. Wydano poprawkę, która przywraca to przepisywanie dla SQL Server 2014 i późniejszych (nie 2012) z włączonymi poprawkami optymalizatora zapytań (np. Flaga śledzenia 4199).


Ale o operatorze logicznej unii wszystkie ( UNIA)? Istnieje UNIAReorderInputstransformacja, która może zmienić kolejność danych wejściowych. Istnieją również dwa fizyczne operatory, których można użyć do zaimplementowania logicznego połączenia Union All UNIAtoCONi UNIAtoMERGE(Union All to Merge Union).

Dlatego wydaje się, że optymalizator zapytań może zmienić kolejność danych wejściowych dla UNION ALL; nie wydaje się jednak, że jest to powszechna transformacja (zerowe użycie UNIAReorderInputsna serwerach SQL, które mam łatwo dostępny. Nie znamy okoliczności, które spowodowałyby użycie optymalizatora UNIAReorderInputs; chociaż z pewnością jest on używany, gdy przewodnik lub użycie planu podpowiedź do planu służy do wymuszenia planu wygenerowanego przy użyciu fizycznych danych o zmienionej kolejności wierszy celu, o których mowa powyżej.

Czy istnieje sposób, aby silnik przetwarzał więcej niż jeden wkład na raz?

Fizyczny operator konkatenacji może istnieć w równoległej części planu. Z pewnym trudem byłem w stanie stworzyć plan z równoległymi konkatenacjami, używając następującego zapytania:

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
    SELECT  userid, RegDate FROM users WHERE userid > 1000000
    UNION 
    SELECT  userid, RegDate FROM users WHERE userid < 1000000
    UNION all
    SELECT userid, RegDate FROM users WHERE userid < 2000000
    ) d ORDER BY RegDate OPTION (RECOMPILE)

Tak więc, w najściślejszym sensie, fizyczny operator konkatenacji wydaje się zawsze przetwarzać dane wejściowe w spójny sposób (pierwszy z góry, drugi z dołu); optymalizator może jednak zmienić kolejność danych wejściowych przed wyborem operatora fizycznego lub użyć połączenia scalającego zamiast konkatenacji.

StrayCatDBA
źródło
8

Według Craiga Freedmana kolejność wykonania dla operatora konkatenacji jest gwarantowana.

Z jego postu na blogu Wyświetlanie planów zapytań na blogach MSDN:

Pamiętaj, że gdy operator ma więcej niż jedno dziecko, kolejność dzieci ma znaczenie. Najwyższe dziecko jest pierwszym dzieckiem, a najniższe dziecko jest drugim. Operator konkatenacji przetwarza dzieci w tej kolejności.

I z książek online Showplan Referencje dla operatorów logicznych i fizycznych

Operator fizyczny Concatenation ma dwa lub więcej danych wejściowych i jedno wyjście. Konkatenacja kopiuje wiersze z pierwszego strumienia wejściowego do strumienia wyjściowego, a następnie powtarza tę operację dla każdego dodatkowego strumienia wejściowego.

Mikael Eriksson
źródło
Ten cytat jest bardzo zbliżony do tego, czego szukałem. Jestem gotów zrobić skok od wykonania w tej kolejności do zwrotu w tej kolejności - chociaż rozczarowuję, że dokumentacja wyklucza w tym przypadku przetwarzanie równoległe.
Gordon Linoff
2

Odpowiedź wiki społeczności :

Nie wiem, czy możesz udowodnić, że każde zaobserwowane zachowanie jest zawsze gwarantowane, w ten czy inny sposób, chyba że możesz wyprodukować kontrprzykład. W przypadku braku tego sposobu, aby naprawić kolejność zwracania wyników, jest oczywiście dodanie ORDER BY.

Nie wiem, czy istnieje „poprawka” lub czy istnieje potrzeba poprawki, jeśli możesz wykazać, że w niektórych scenariuszach zapytania są przetwarzane w innej kolejności.

Brak wyraźnej, oficjalnej dokumentacji sugeruje, że nie powinieneś na tym polegać. Właśnie z tego powodu ludzie mieli kłopoty z ORDER BYpunktu widzenia i GROUP BYbez niej ORDER BY, 8 lat temu, kiedy został wydany optymalizator SQL Server 2005.

Ze wszystkimi nowymi funkcjami w nowszych wersjach programu SQL Server (z większą liczbą nadchodzących), nawet jeśli uważasz, że możesz dziś zagwarantować określone zachowanie, nie spodziewałbym się, że będzie to prawdziwe (dopóki nie zostanie to udokumentowane).

Nawet jeśli nie zależysz od tego zachowania, co zamierzasz zrobić z wynikami? W każdym razie, ja nie nazwałbym Simple Talk artykuł outsiderem urzędnika . Z tego, co wiemy, jest to tylko przypuszczenie oparte na obserwacji.

Microsoft nigdy nie opublikuje oficjalnej dokumentacji stwierdzającej, że „x” nie ma gwarancji, że zrobi to „y”. Jest to jeden z powodów, dla których wciąż, prawie dekadę później, mamy problemy z przekonaniem ludzi, że nie mogą polegać na zaobserwowanym zamówieniu bez ORDER BY- nie ma dokumentacji, która mówi „nie jest to gwarantowane”.

rev użytkownik126897
źródło