> [!TIP] > Recept z [kuchárky exekučných plánov](script.php?id=64&s=exekucne-plany-kucharka-zacni-tu). Ukážky bežia v testovacej databáze [PlanLab](script.php?id=65&s=planlab-testovacia-databaza-pre-recepty-exekucnych-planov) – nikdy ich nespúšťaj na produkcii. ## Ako to vyzerá v pláne  V SSMS: operátor **Parallelism** s logickou operáciou **Distribute Streams**, **Repartition Streams** alebo **Gather Streams**. Operátory, ktoré bežia vo viacerých vláknach, majú pri ikone **žlté koliesko s dvoma šípkami**. Na SELECT je vlastnosť **Degree of Parallelism**. ## Čo to znamená Paralelný plán rozdelí prácu medzi viac vlákien (*DOP* – degree of parallelism). Operátory **Parallelism** (*exchange*) prenášajú riadky medzi skupinami vlákien: - **Distribute Streams** – z jedného vlákna do viacerých. - **Repartition Streams** – z N vlákien do N vlákien, napr. aby riadky s rovnakým kľúčom skončili v tom istom vlákne pred spojením alebo agregáciou. - **Gather Streams** – z viacerých vlákien do jedného (zvyčajne tesne pred SELECT). ### Do hĺbky - **Partitioning Type** (F4 pri Repartition / Distribute) – *Hash*, *Round Robin*, *Broadcast* (malý vstup sa pošle každému vláknu), *Range*. - **Order By** pri Gather Streams = *order-preserving exchange* – vlákna musia odovzdávať v poradí; pri nerovnomerných vláknach to brzdí. - **Actual Number of Rows** pri paralelnom operátore sa dá rozbaliť **po vláknach**. Veľký nepomer = **skew**: jedno vlákno robí väčšinu práce, ostatné čakajú. - Čakanie výmenníkov je **CXPACKET** a **CXCONSUMER** (rozdelené od 2016 SP2 / 2017 CU3), v novších verziách aj **CXSYNC_PORT** a **CXSYNC_CONSUMER** – viď [Čakania](waits.php#CXPACKET). - **Exchange spill** – varovanie, keď výmenník nestíhal a musel riadky odložiť do tempdb (typicky pri order-preserving exchange, keď by sa vlákna navzájom zastavili). - **NonParallelPlanReason** na SELECT povie, prečo plán **nemohol** byť paralelný (napr. skalárna funkcia, `MAXDOP 1`, table variable modifikácia). - Paralelný plán sa zvažuje, keď odhadovaný náklad sériového plánu prekročí **cost threshold for parallelism** – viď [Paralelizmus – cost threshold, MAXDOP](script.php?id=93&s=paralelizmus-cost-threshold-maxdop-a-cxpacket-cxconsumer). ## Kedy je to v poriadku / kedy problém | V poriadku | Problém | |---|---| | veľký report, vlákna rovnomerne vyťažené | malý OLTP dotaz s paralelným plánom (vysoký počet volaní) | | CPU time > elapsed time (vlákna pracujú naraz) | skew – jedno vlákno má skoro všetky riadky | | Gather Streams tesne pred SELECT | order-preserving Gather s exchange spillom | ## Ako si to vyskúšať ```sql USE PlanLab; SET STATISTICS TIME ON; -- 1) Paralelný plán (ak má server viac jadier a náklad prekročí cost threshold) SELECT ProductID, SUM(Qty * Price) AS trzba FROM dbo.OrderLines GROUP BY ProductID OPTION (MAXDOP 4); -- 2) Ten istý dotaz sériovo – porovnaj CPU time a elapsed time SELECT ProductID, SUM(Qty * Price) AS trzba FROM dbo.OrderLines GROUP BY ProductID OPTION (MAXDOP 1); -- 3) Skew: zákazník 1 má 100 000 objednávok, ostatní pár kusov SELECT o.CustomerID, SUM(l.Qty) AS kusy FROM dbo.Orders AS o JOIN dbo.OrderLines AS l ON l.OrderID = o.OrderID GROUP BY o.CustomerID OPTION (MAXDOP 4); ``` Spusti s **Include Actual Execution Plan** (Ctrl+M). Na SELECT pozri *Degree of Parallelism*, pri operátoroch rozbaľ *Actual Number of Rows* po vláknach. Ak plán ostane sériový, pozri na SELECT *NonParallelPlanReason* alebo nastavenie *cost threshold for parallelism* servera. ## Čo s tým 1. Paralelizmus je dobrý pre veľké dotazy. Rieš ho, keď **malé časté dotazy** idú paralelne (zvýš *cost threshold for parallelism*) alebo keď je **skew**. 2. Pri skew pozri dáta (jedna hodnota má väčšinu riadkov) a štatistiky; niekedy pomôže prepis dotazu alebo iný typ spojenia. 3. MAXDOP pre konkrétny dotaz meň hintom len výnimočne – nastavenie servera / databázy rieši recept [Paralelizmus – cost threshold, MAXDOP](script.php?id=93&s=paralelizmus-cost-threshold-maxdop-a-cxpacket-cxconsumer). ## Súvisiace - [Paralelizmus – cost threshold, MAXDOP a CXPACKET](script.php?id=93&s=paralelizmus-cost-threshold-maxdop-a-cxpacket-cxconsumer) - [Hash Match](script.php?id=73&s=hash-match-hash-join-a-hash-aggregate-build-a-probe) - [Čakanie CXPACKET](waits.php#CXPACKET) - [Čakanie CXCONSUMER](waits.php#CXCONSUMER) - [Top 20 dotazov podľa CPU](script.php?id=5&s=top-20-dotazov-podla-cpu) ## Zdroje - [Microsoft Learn – Showplan Logical and Physical Operators Reference](https://learn.microsoft.com/sql/relational-databases/showplan-logical-and-physical-operators-reference) - [Microsoft Learn – Query Processing Architecture Guide](https://learn.microsoft.com/sql/relational-databases/query-processing-architecture-guide) - [Microsoft Learn – Configure the max degree of parallelism](https://learn.microsoft.com/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option) - [Hugo Kornelis – SQL Server Execution Plan Reference (SQLServerFast)](https://sqlserverfast.com/epr/) - [Paul White – SQLkiwi (články o optimalizátore a operátoroch)](https://www.sql.kiwi/) _Texty sú vlastné, tvrdenia overené proti uvedeným zdrojom (11/2026). T-SQL je staticky skontrolovaný, nie spustený na živom serveri – vyskúšaj ho najprv v PlanLab._
Paralelizmus v pláne – Distribute, Repartition a Gather Streams
Paralelné operátory v pláne: Distribute, Repartition a Gather Streams, Partitioning Type, rozdelenie riadkov po vláknach (skew), exchange spill, NonParallelPlanReason a čakania CXPACKET / CXCONSUMER.