sql >> Databáze >  >> RDS >> Database

Jak se spouštějí paralelní plány – část 4

Toto je čtvrtá část z pětidílné série, která se hluboce ponoří do způsobu, jakým se začnou provádět paralelní plány SQL Server v režimu řádků. Část 1 inicializovala kontext provádění nula pro nadřazenou úlohu a část 2 vytvořila strom skenování dotazů. Část 3 zahájila skenování dotazů a provedla určitou ranou fázi zpracování a spustil první další paralelní úlohy ve větvi C.

Podrobnosti o provedení větve C

Toto je druhý krok prováděcí sekvence:

  1. Větev A (nadřazený úkol).
  2. Větev C (další paralelní úlohy).
  3. Větev D (další paralelní úkoly).
  4. Větev B (další paralelní úkoly).

Připomenutí poboček v našem paralelním plánu (kliknutím zvětšíte)

Krátce po nových úkolech pro větev C jsou ve frontě, SQL Server připojí pracovníka ke každému úkolu a umístí pracovníka do plánovače připravena k provedení. Každá nová úloha běží v novém kontextu provádění. Na DOP 2 jsou dvě nové úlohy, dvě pracovní vlákna a dva kontexty provádění pro větev C. Každá úloha spouští vlastní kopii iterátorů ve větvi C ve svém vlastním pracovním vláknu:

Dvě nové paralelní úlohy začnou běžet v dílčím postupu vstupní bod, který zpočátku vede k Open volání na straně výrobce burzy (CQScanXProducerNew::Open ). Oba úkoly mají na začátku svého života identické zásobníky volání:

Synchronizace Exchange

Mezitím nadřazený úkol (běží na vlastním pracovním vláknu) zaregistruje nové podprocesy u správce podprocesů a poté čeká na straně spotřebitele výměny přerozdělovacích proudů v uzlu 5. Nadřazená úloha čeká na CXPACKET * do všech paralelních úloh větve C dokončí své Open zavolá a vrátí se na stranu výrobce ústředny. Paralelní úlohy otevřou každý iterátor v jejich podstromu (tj. až po hledání indexu v uzlu 9 a zpět), než se vrátíte k výměně toků přerozdělení v uzlu 5. Nadřazená úloha bude čekat na CXPACKET zatímco se to stane. Pamatujte, že nadřazená úloha provádí volání raných fází.

Toto čekání můžeme vidět v čekajících úlohách DMV:

Kontext nula provádění (nadřazený úkol) je blokován oběma novými kontexty provádění. Tyto kontexty provádění jsou prvními dalšími, které se vytvoří po kontextu nula, takže jsou jim přiřazena čísla jedna a dvě. Pro zdůraznění:Oba nové kontexty provádění potřebují otevřít své podstromy a vrátit se k výměně pro nadřazený úkol CXPACKET počkejte na konec.

Možná jste očekávali, že uvidíte CXCONSUMER čeká zde, ale toto čekání je vyhrazeno pro čekání na data řádku přijet. Aktuální čekání není pro řádkyotevření je na straně výrobce , takže dostaneme obecný CXPACKET * počkat.

* Azure SQL Database a spravovaná instance používají nový CXSYNC_PORT počkejte místo CXPACKET zde, ale toto vylepšení se ještě nedostalo do SQL Serveru (od roku 2019 CU9).

Kontrola nových paralelních úloh

Nové úkoly můžeme vidět v profilech dotazů DMV. Profilovací informace pro nové úlohy se objevují v DMV, protože jejich kontexty provádění byly odvozeny (klonovány a poté aktualizovány) z nadřazeného (kontext provádění nula):

Ve větvi C jsou nyní tři položky pro každý iterátor (zvýrazněno). Jeden pro nadřazenou úlohu (kontext provádění nula) a jeden pro každou novou další paralelní úlohu (kontexty 1 a 2). Všimněte si, že odhadovaný počet řádků na vlákno (viz část 1) nyní dorazily a jsou zobrazeny pouze pro paralelní úlohy. První a poslední aktivita protože paralelní úlohy představují dobu, kdy byly vytvořeny kontexty jejich provádění. Žádný z nových úkolů se neotevřel zatím nějaké iterátory.

Přerozdělovací proudy výměna v uzlu 5 má stále pouze jeden záznam na výstupu DMV. Je to proto, že přidružený neviditelný profiler sleduje spotřebitele straně výměny. Další paralelní úlohy jsou u producenta straně výměny. Spotřebitelská strana uzlu 5 bude nakonec máme paralelní úkoly, ale k tomuto bodu jsme se ještě nedostali.

Kontrolní bod

Zdá se, že je to dobrý bod k pauze, abychom se nadechli a shrnuli, kde se v tuto chvíli všechno nachází. Postupem času bude těchto zastávek přibývat.

  • Rodičovský úkol je na straně spotřebitele výměny přerozdělovacích toků v uzlu 5 , čekající na CXPACKET . Je uprostřed provádění hovorů rané fáze. Pozastavil se, aby se spustila větev C, protože tato větev obsahuje blokující řazení. Čekání nadřazené úlohy bude pokračovat, dokud obě paralelní úlohy nedokončí otevření svých podstromů.
  • Dva nové paralelní úlohy na straně výrobce uzlu 5 burzy jsou připraveny otevřít iterátory ve větvi C.

Nic mimo větev C tohoto plánu paralelního provádění nemůže pokročit vpřed, dokud nebude nadřazený úkol uvolněn z jeho CXPACKET Počkejte. Pamatujte, že jsme zatím vytvořili pouze jednu sadu dalších paralelních pracovníků pro větev C. Jediným dalším vláknem je nadřazená úloha a ta je blokována.

Paralelní provádění větve C

Tyto dva paralelní úkoly začínají na straně výrobce výměny přerozdělovacích toků v uzlu 5. Každý z nich má samostatný (sériový) plán s vlastním agregováním toku, řazením a hledáním indexu. Výpočetní skalár se nezobrazuje v runtime plánu, protože jeho výpočty jsou odloženy na řazení.

Každá instance hledání indexu je podporována paralelně a funguje na nesouvislých sadách řádků. Tyto sady jsou generovány na vyžádání z nadřazené sady řádků vytvořené dříve nadřazeným úkolem (popsané v části 1). Když některá z instancí hledání potřebuje nový podrozsah řádků, synchronizuje se s ostatními pracovními vlákny, takže pouze jeden přiděluje nový podrozsah ve stejnou dobu. Použitý synchronizační objekt byl také dříve vytvořen nadřazenou úlohou. Když úloha čeká na výhradní přístup k nadřazené sadě řádků, aby získala nový podrozsah, čeká na CXROWSET_SYNC .

Otevřeny úkoly větve C

Sekvence Open volání pro každý úkol ve větvi C je:

  • CQScanXProducerNew::Open . Všimněte si, že na straně výrobce výměny není žádný předchozí profiler. To je nešťastné pro tunery dotazů.
  • CXTransLocal::Open
  • CXPort::Register
  • CXTransLocal::ActivateWorkers
  • CQScanProfileNew::Open . Profiler nad uzlem 6.
  • CQScanStreamAggregateNew::Open (uzel 6)
  • CQScanProfileNew::Open . Profiler nad uzlem 7.
  • CQScanSortNew::Open (uzel 7)

Řazení je plně blokující operátor . Během Open spotřebuje celý svůj vstup volání. Zde je k prozkoumání velké množství zajímavých vnitřních detailů, ale místa je málo, takže se budu věnovat pouze těm nejdůležitějším:

Řazení vytvoří svou třídicí tabulku otevřením jejího podstromu a spotřebováním všech řádků, které mohou poskytnout její potomci. Jakmile je řazení dokončeno, je řazení připraveno k přechodu do výstupního režimu a vrátí řízení svému nadřazenému prvku. Řazení bude později reagovat na GetRow() volání a pokaždé vrátí další seřazený řádek. Ilustrativní zásobník volání při zadávání řazení je:

Provádění pokračuje, dokud každé řazení nespotřebuje všechny (nesouvislé rozsahy) řádků dostupné z jeho podřízeného hledání indexu . Řazení pak volají Close na indexu vyhledá a vrátí řízení jejich nadřazenému agregátu proudu . Agregáty proudu inicializují svá počítadla a vrátí řízení výrobci straně výměny rozdělení v uzlu 5. Sekvence Open volání je nyní v této větvi dokončeno.

Profilující DMV v tomto bodě ukazuje aktualizované časové údaje a časy uzavření pro paralelní index hledá:

Více synchronizace výměn

Připomeňme, že nadřazený úkol čeká na spotřebitele straně uzlu 5, aby se otevřeli všichni výrobci. Podobný proces synchronizace nyní probíhá mezi paralelními úlohami na producentu strana stejné burzy:

Každá úloha producenta se synchronizuje s ostatními pomocí CXTransLocal::Synchronize . Producenti volají CXPort::Open a poté počkejte na CXPACKET pro všechny strany spotřebitelů otevřít paralelní úlohy. Když první paralelní úloha větve C dorazí zpět na stranu producenta burzy a čeká, čekající úlohy DMV vypadají takto:

Stále máme čekání na spotřebitelské straně nadřazeného úkolu. Nový CXPACKET zvýrazněno je naše první paralelní úloha na straně výrobce, která čeká na všechny paralelní úlohy na straně spotřebitele otevřete port pro výměnu.

Paralelní úlohy na straně spotřebitele (ve větvi B) ještě ani neexistují, takže úloha producenta zobrazuje NULL pro kontext provádění, kterým je blokována. Úloha, která aktuálně čeká na spotřebitelské straně výměny přerozdělovacích proudů, je nadřazená úloha (nikoli paralelní úloha!) spuštěná EarlyPhases kód, takže se to nepočítá.

Nadřazený úkol CXPACKET čekání končí

Když druhé paralelní úloha ve větvi C se vrací zpět na stranu producenta ústředny z Open volání, všichni výrobci otevřeli výměnný port, takže nadřazený úkol na straně spotřebitele burzy uvolněno z jeho CXPACKET počkat.

Pracovníci na straně výrobce nadále čekají na vytvoření paralelních úloh na straně spotřebitele a otevřou port pro výměnu:

Kontrolní bod

V tomto okamžiku:

  • Celkem jsou tři úkoly:Dva ve větvi C plus nadřazený úkol.
  • Oba producenti v uzlu 5 se ústředna otevřela a čekají na CXPACKET pro otevření paralelních úloh na straně spotřebitele. Většinu mechanismu výměny (včetně vyrovnávací paměti řádků) vytváří spotřebitelská strana, takže výrobci zatím nemají kam vkládat řádky.
  • Třídy ve větvi C spotřebovali veškerý svůj vstup a jsou připraveni poskytnout tříděný výstup.
  • index hledá v pobočce C dokončili svou práci a ukončili činnost.
  • Rodičovský úkol byl právě uvolněn z čekání na CXPACKET na spotřebitelské straně uzlu si vyměňuje 5 přerozdělovacích toků. Je to stále provádění vnořených EarlyPhases hovory.

Zahájení paralelních úloh větve D

Toto je třetí krok v pořadí provádění:

  1. Větev A (nadřazený úkol).
  2. Větev C (další paralelní úlohy).
  3. Větev D (další paralelní úkoly).
  4. Větev B (další paralelní úkoly).

Vydáno z jeho CXPACKET čekat na spotřebitelské straně výměny toků přerozdělení v uzlu 5, nadřazený úkol vzestupuje strom skenování dotazů větve B. Vrací se z vnořených EarlyPhases volání na různé iterátory a profilery na vnějším (horním) vstupu slučovacího spojení.

Jak již bylo zmíněno, vzestupně strom aktualizuje uplynulé časy a časy CPU zaznamenané neviditelnými iterátory profilování. Spouštíme kód pomocí nadřazené úlohy, takže tato čísla jsou zaznamenána proti kontextu provádění nula. Toto je konečný zdroj časových čísel „vlákna 0“ zmíněných v mém předchozím článku Porozumění časování operátora prováděcího plánu.

Jakmile se vrátíte do sloučení, nadřazená úloha zavolá EarlyPhases pro iterátory a profilery na vnitřním (spodním) vstupu slučovacího spojení. Toto jsou uzly 10 až 15 (kromě 14, které je odloženo):

Jakmile volání raných fází nadřazené úlohy dosáhnou hledání indexu v uzlu 15, začne strom znovu stoupat (nastavení časů profilování), dokud nedosáhne výměny přerozdělovacích proudů v uzlu 11.

Poté, stejně jako na vnějším (horním) vstupu slučovacího spojení, spustí stranu producenta ústředny v uzlu 11 , čímž se vytvoří dva nové paralelní úlohy .
To uvede větev D do pohybu (zobrazeno níže). Větev D se provádí přesně tak, jak již bylo podrobně popsáno pro větev C.

Ihned po spuštění úloh pro větev D nadřazená úloha čeká na CXPACKET v uzlu 11, aby noví producenti otevřeli výměnný port:

Nový CXPACKET čekání jsou zvýrazněna. Všimněte si, že nahlášené ID uzlu může být trochu zavádějící. Nadřazená úloha skutečně čeká na spotřebitelské straně uzlu 11 (přerozdělení toků), nikoli uzlu 2 (shromáždit toky). Toto je zvláštnost zpracování rané fáze.

Mezitím produkční vlákna ve větvi C nadále čekají na CXPACKET aby se na spotřebitelské straně uzlu otevřelo 5 přerozdělovacích toků.

Otevření pobočky D

Těsně poté, co nadřazený úkol spustí producenty pro větev D, profil dotazu DMV zobrazuje nové kontexty provádění (3 a 4):

Dva nové paralelní úkoly ve větvi D postupují stejně jako ve větvi C. Třídění spotřebuje veškerý svůj vstup a úkoly větve D se vrátí do výměny. Tím se uvolní nadřazená úloha z jejího CXPACKET Počkejte. Pracovníci pobočky D pak čekají na CXPACKET na straně producenta uzlu 11 pro otevření paralelních úloh na straně spotřebitele. Tito paralelní pracovníci (ve větvi B) zatím neexistují.

Kontrolní bod

Čekací úlohy v tomto bodě jsou uvedeny níže:

Obě sady paralelních úloh ve větvích C a D čekají na CXPACKET pro jejich paralelní úlohu, kterou spotřebitelé otevřou, si při přerozdělování toků vymění uzly 5 a 11, v tomto pořadí. Jediná spustitelná úloha v celém dotazu je právě teď nadřazený úkol .

Profiler dotazu DMV v tomto bodě je zobrazen níže se zvýrazněnými operátory ve větvích C a D:

Jediné paralelní úkoly, které jsme ještě nezačali, jsou ve větvi B. Veškerá práce na větvi B byla zatím počáteční fáze volání provedená nadřazeným úkolem .

Konec 4. části

V závěrečné části této série popíšu, jak se spustí zbytek tohoto konkrétního plánu paralelního provádění, a stručně popíšu, jak plán vrací výsledky. Zakončím obecnějším popisem, který platí pro paralelní plány libovolné složitosti.


  1. PLS-00103:Setkal se se symbolem CREATE

  2. ORA-00904 neplatný identifikátor na dekódovacím aliasu

  3. Oracle 10g - optimalizujte WHERE IS NOT NULL

  4. Jak vytvořit tabulku v MySQL