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

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

Tato pětidílná série se hluboce ponoří do způsobu spouštění paralelních plánů v režimu řádků SQL Server. Tato první část pokrývá roli nadřazeného úkolu (koordinátora) při přípravě plánu pro paralelní realizaci. Zahrnuje inicializaci každého operátora a přidávání skrytých profilerů ke shromažďování údajů o výkonu za běhu, jako je skutečný počet řádků a uplynulý čas.

Nastavení

Abychom poskytli konkrétní základ pro analýzu, budeme sledovat, jak konkrétní paralelní dotaz začíná provádění. Použil jsem veřejný Stack Overflow 2013 databáze (podrobnosti ke stažení). Požadovaný tvar plánu lze také získat na základě menšího souboru dat Stack Overflow 2010, pokud je to pohodlnější. Lze jej stáhnout na stejném odkazu. Přidal jsem jeden neshlukovaný index:

CREATE NONCLUSTERED INDEX PP
ON dbo.Posts
(
    PostTypeId ASC,
    CreationDate ASC
);

Moje testovací prostředí je SQL Server 2019 CU9 na notebooku s 8 jádry a 16 GB paměti přidělené instanci. Úroveň kompatibility 150 se používá výhradně. Tyto podrobnosti uvádím, abych vám pomohl reprodukovat cílový plán, pokud si to přejete. Základy paralelního spouštění v režimu řádků se od SQL Server 2005 nezměnily, takže následující diskuse je široce použitelná.

Testovací dotaz vrátí celkový počet otázek a odpovědí seskupených podle měsíce a roku:

WITH 
    MonthlyPosts AS 
    (
        SELECT 
            P.PostTypeId, 
            CA.TheYear, 
            CA.TheMonth, 
            Latest = MAX(P.CreationDate)
        FROM dbo.Posts AS P
        CROSS APPLY 
        (
            VALUES
            (
                YEAR(P.CreationDate), 
                MONTH(P.CreationDate)
            )
        ) AS CA (TheYear, TheMonth)
        GROUP BY 
            P.PostTypeId, 
            CA.TheYear, 
            CA.TheMonth
    )
SELECT 
    rn = ROW_NUMBER() OVER (
        ORDER BY Q.TheYear, Q.TheMonth),
    Q.TheYear, 
    Q.TheMonth, 
    LatestQuestion = Q.Latest,
    LatestAnswer = A.Latest
FROM MonthlyPosts AS Q
JOIN MonthlyPosts AS A
    ON A.TheYear = Q.TheYear
    AND A.TheMonth = Q.TheMonth
WHERE 
    Q.PostTypeId = 1
    AND A.PostTypeId = 2
ORDER BY 
    Q.TheYear,
    Q.TheMonth
OPTION 
(
    USE HINT ('DISALLOW_BATCH_MODE'),
    USE HINT ('FORCE_DEFAULT_CARDINALITY_ESTIMATION'),
    ORDER GROUP,
    MAXDOP 2
);

Použil jsem rady k získání konkrétního plánu režimu řádku tvaru. Provedení je omezeno na DOP 2, aby byly některé podrobnosti zobrazené později stručnější.

Odhadovaný plán provádění je (kliknutím zvětšíte):

Pozadí

Optimalizátor dotazů vytvoří jeden zkompilovaný plán pro dávku. Každý výpis v dávce je označen pro sériové nebo paralelní provedení v závislosti na způsobilosti a odhadovaných nákladech.

Paralelní plán obsahuje výměny (operátory paralelismu). Výměny se mohou objevit v distribučních streamech , přerozdělovací proudy nebo shromáždit streamy formulář. Každý z těchto typů ústředny používá stejné základní komponenty, jen jinak propojené, s různým počtem vstupů a výstupů. Další informace o paralelním provádění v režimu řádků naleznete v části Plány paralelního provádění – větve a vlákna.

DOP downgrade

Stupeň paralelismu (DOP) pro paralelní plán lze v případě potřeby za běhu snížit. Paralelní dotaz může začít vyžadovat DOP 8, ale bude postupně downgradován na DOP 4, DOP 2 a nakonec DOP 1 kvůli nedostatku systémových prostředků v daném okamžiku. Pokud byste to chtěli vidět v akci, podívejte se na toto krátké video od Erika Darlinga.

Spuštění paralelního plánu na jednom vláknu může také nastat, když je paralelní plán uložený v mezipaměti znovu použit relací, která je omezena na DOP 1 nastavením prostředí (např. maska ​​afinity nebo regulátor prostředků). Podrobnosti naleznete v části Mýtus:SQL Server ukládá sériový plán do mezipaměti s každým paralelním plánem.

Ať už je příčina jakákoli, downgrade DOP paralelního plánu uloženého v mezipaměti není výsledkem je sestavení nového sériového plánu. SQL Server znovu použije stávající paralelní plán zakázáním výměny. Výsledkem je „paralelní“ plán, který se provádí na jednom vláknu. Ústředny se stále objevují v plánu, ale za běhu jsou vynechány.

SQL Server nemůže povýšit sériový plán na paralelní provádění přidáním výměn za běhu. To by vyžadovalo novou kompilaci.

Inicializace paralelního plánu

Paralelní plán má všechny výměny potřebné k využití dalších pracovních vláken, ale je zde další nastavení potřebné za běhu před zahájením paralelního provádění. Jedním zřejmým příkladem je, že pro konkrétní úkoly v rámci plánu musí být přidělena další pracovní vlákna, ale je toho mnohem víc.

Začnu v bodě, kde byl z mezipaměti plánů načten paralelní plán. V tomto okamžiku existuje pouze původní vlákno zpracovávající aktuální požadavek. Tomuto vláknu se někdy v paralelních plánech říká „koordinátorské vlákno“, ale já dávám přednost výrazům „nadřazený úkol “ nebo „rodičovský pracovník“. Jinak na tomto vláknu není nic zvláštního; je to stejné vlákno, které připojení používá ke zpracování požadavků klientů a spouštění sériových plánů až do konce.

Chcete-li zdůraznit, že existuje pouze jedno vlákno právě teď chci, abyste si plán v tomto okamžiku představili takto:

V tomto příspěvku budu téměř výhradně používat snímky obrazovky z Sentry One Plan Explorer, ale pouze pro toto první zobrazení ukážu také verzi SSMS:

V obou reprezentacích je klíčovým rozdílem nedostatek ikon paralelismu u každého operátora, i když jsou výměny stále přítomny. Momentálně existuje pouze nadřazená úloha, která běží na původním vláknu připojení. Žádná další pracovní vlákna byly dosud rezervovány, vytvořeny nebo přiřazeny úkoly. Mějte na mysli výše uvedené znázornění plánu, jak budeme pokračovat.

Vytvoření spustitelného plánu

Plán je v tuto chvíli v podstatě jen šablona které lze použít jako základ pro budoucí provedení. Aby byl SQL Server připraven pro konkrétní běh, musí vyplnit hodnoty za běhu, jako je aktuální uživatel, kontext transakce, hodnoty parametrů, ID pro jakékoli objekty vytvořené za běhu (např. dočasné tabulky a proměnné) a tak dále.

Pro paralelní plán musí SQL Server provést poměrně dost dalších přípravných prací, aby se vnitřní strojní zařízení dostalo do bodu, kdy může začít provádění. Pracovní vlákno nadřazeného úkolu je zodpovědné za provádění téměř veškeré této práce (a jistě i veškeré práce, kterou pokryjeme v části 1).

Proces transformace šablony plánu pro konkrétní běh je známý jako vytvoření spustitelného plánu . Někdy je obtížné udržet terminologii přímočarou, protože termíny jsou často přetížené a nesprávně používané (dokonce i ze strany společnosti Microsoft), ale udělám vše pro to, abych byl co nejdůslednější.

Kontexty provádění

Můžete si představit kontext provádění jako šablona plánu naplněná všemi specifickými informacemi o běhu, které konkrétní vlákno potřebuje. Spustitelný plán pro seriál se skládá z jednoho kontextu provádění, kde jediné vlákno spouští celý plán.

Paralelní spustitelný plán obsahuje kolekci kontextů provádění :Jeden pro nadřazenou úlohu a jeden na vlákno v každé paralelní větvi. Každé další paralelní pracovní vlákno spouští svou část celkového plánu v rámci vlastního kontextu provádění. Například paralelní plán se třemi větvemi běžícími na DOP 8 má (1 + (3 * 8)) =25 kontextů provádění. Kontexty sériového spuštění se ukládají do mezipaměti pro opětovné použití, ale další kontexty paralelního spuštění nikoli.

Nadřazená úloha vždy existuje před dalšími paralelními úlohami, takže je jí přiřazen kontext provádění nula . Prováděcí kontexty používané paralelními pracovníky budou vytvořeny později, až bude nadřazený kontext plně inicializován. Další kontexty jsou klonovány z nadřazeného kontextu a poté přizpůsobené pro jejich konkrétní úkol (to je popsáno v části 2).

Spouštění kontextu nula zahrnuje řadu činností. Je nepraktické pokoušet se je všechny vyjmenovat, ale bude užitečné pokrýt některé z hlavních, které se vztahují na náš testovací dotaz. Na jeden seznam jich bude stále příliš mnoho, takže je rozdělím do (poněkud libovolných) sekcí:

1. Inicializace nadřazeného kontextu

Když odešleme příkaz k provedení, kontext nadřazené úlohy (kontext nula) se inicializuje pomocí:

  • Odkaz na základní transakci (explicitní, implicitní nebo automatický závazek). Paralelní pracovníci budou provádět dílčí transakce, ale všechny jsou zahrnuty v rámci základní transakce.
  • Seznam parametrů příkazu a jejich aktuální hodnoty.
  • Primární objekt paměti (PMO) používané ke správě přidělení a přidělení paměti.
  • Propojená mapa operátorů (dotazových uzlů) ve spustitelném plánu.
  • Továrna na jakýkoli požadovaný velký objekt (blob) úchyty.
  • Uzamkněte třídy, abyste měli přehled o několika uzamčeních držených po určitou dobu během provádění. Ne všechny plány vyžadují třídy uzamčení protože operátoři plně streamingu obvykle postupně zamykají a odemykají jednotlivé řádky.
  • Odhadovaná dotace paměti pro dotaz.
  • Udělování zpětné vazby paměti v režimu řádků struktury pro každý operátor (SQL Server 2019).

Mnoho z těchto věcí bude později použito nebo odkazováno na paralelní úlohy, takže musí nejprve existovat v nadřazeném rozsahu.

2. Metadata nadřazeného kontextu

Další hlavní prováděné úkoly jsou:

  • Kontrola odhadované ceny dotazu je v rámci limitu nastaveného možnostmi konfigurace limitu nákladů guvernéra dotazu.
  • Aktualizace použití indexu záznamy – vystavené prostřednictvím sys.dm_db_index_usage_stats .
  • Vytvoření hodnot výrazů uložených v mezipaměti (běhových konstant).
  • Vytvoření seznamu operátorů profilování používá se ke shromažďování metrik za běhu, jako jsou počty řádků a časování, pokud to bylo požadováno pro aktuální provádění. Samotné profilery ještě nejsou vytvořeny, pouze seznam.
  • Pořízení snímku čekání pro funkci čekání na relace vystavenou prostřednictvím sys.dm_exec_session_wait_stats .

3. DOP a přidělení paměti

Kontext nadřazeného úkolu nyní:

  • Vypočítá stupeň paralelismu za běhu (DOP ). To je ovlivněno počtem volných pracovníků (viz dříve „DOP downgrade“), kam je lze umístit mezi uzly, a množstvím příznaků trasování.
  • Rezervuje požadovaný počet vláken. Tento krok je čistě účetní – vlákna samotná v tomto okamžiku nemusí existovat. SQL Server sleduje maximální počet vláken, která může mít. Rezervace vláken odečte od tohoto čísla. Po dokončení vláken se maximální počet opět zvýší.
  • Nastaví časový limit přidělení paměti .
  • Vypočítá přidělení paměti, včetně paměti potřebné pro výměnné vyrovnávací paměti.
  • Získává přidělení paměti prostřednictvím příslušného semaforu prostředků .
  • Vytváří objekt správce pro zpracování paralelních podprocesů . Nadřazený úkol je proces nejvyšší úrovně; další úlohy jsou také známé jako podprocesy .

Zatímco vlákna jsou v tomto okamžiku „rezervována“, SQL Server může stále narazit na THREADPOOL čeká později, když se pokusí použít jedno z „rezervovaných“ vláken. Rezervace zaručuje, že SQL Server zůstane po celou dobu kolem svého nakonfigurovaného maximálního počtu vláken, ale fyzické vlákno nemusí být okamžitě dostupné z fondu vláken . Když k tomu dojde, bude muset operační systém spustit nové vlákno, což může chvíli trvat. Více o tom viz Unusual THREADPOOL Waits od Joshe Darnella.

4. Nastavení skenování dotazů

Plány v režimu řádků se spouštějí iterativně móda, počínaje kořenem. Plán, který v tuto chvíli máme, ještě není schopen tohoto způsobu provedení. Stále jde z velké části o šablonu, i když již obsahuje značné množství informací specifických pro provedení.

SQL Server potřebuje převést aktuální strukturu na strom iterátorů , každý s metodami jako Open , GetRow a Close . Metody iterátoru jsou připojeny ke svým potomkům pomocí ukazatelů funkcí. Například volání GetRow na root rekurzivně volá GetRow na podřízených operátorech, dokud není dosaženo úrovně listu a řádek nezačne „bublat“ strom. Pro osvěžení podrobností viz Iterátory, plány dotazů a proč běží zpětně.

Konec 1. části

Udělali jsme dobrý pokrok v nastavení kontextu provádění pro nadřazený úkol. V části 2 budeme sledovat, jak SQL Server vytváří strom skenování dotazů nezbytný pro iterativní provádění.


  1. Dynamický SQL – EXEC(@SQL) versus EXEC SP_EXECUTESQL(@SQL)

  2. Generování dat a kvalita hardwaru

  3. Nasazení zabezpečené multicloudové replikace MySQL na AWS a GCP s VPN

  4. Vše, co potřebujete vědět o SQL CTE na jednom místě