> [!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 **skutočnom** pláne na koreňovom SELECT (F4): **WaitStats** – zoznam čakaní dotazu (typ, čas, počet) a **QueryTimeStats** – *CpuTime* a *ElapsedTime*. Sú tam od SQL Server 2016 SP1 (a v novších verziách SSMS aj prehľadne v Properties). ## Čo to znamená Elapsed čas dotazu = práca (CPU) + **čakanie**. Keď je elapsed oveľa väčší ako CPU, dotaz väčšinu času čakal – a WaitStats povie na čo. Niektoré čakania ukazujú **na plán** (čítanie z disku kvôli skenu, čakanie na pamäť kvôli veľkému grantu), iné **mimo plánu** (iná session drží riadky, klient pomaly preberá výsledky). Podrobné vysvetlenie jednotlivých typov je na stránke [Čakania](waits.php). ### Do hĺbky – čakanie → kde hľadať v pláne | Čakanie | Čo to znamená pre plán | Recept | |---|---|---| | [PAGEIOLATCH_SH / _EX](waits.php#PAGEIOLATCH_SH) | stránky sa čítali z disku – veľa čítaní | [Scan](script.php?id=68&s=table-scan-a-clustered-index-scan-citanie-celej-tabulky), [Key Lookup](script.php?id=70&s=key-lookup-a-rid-lookup-dohladanie-chybajucich-stlpcov), [Non-SARGable](script.php?id=89&s=non-sargable-podmienky-funkcia-na-stlpci-like-x-or) | | [RESOURCE_SEMAPHORE](waits.php#RESOURCE_SEMAPHORE) | čakanie na memory grant | [Memory grant](script.php?id=91&s=memory-grant-kolko-pamate-dostal-dotaz-privela-alebo-primalo), [Spill](script.php?id=90&s=spill-do-tempdb-sort-a-hash-warning-memory-grant-feedback) | | [CXPACKET](waits.php#CXPACKET) / [CXCONSUMER](waits.php#CXCONSUMER) | výmena riadkov medzi vláknami | [Paralelizmus v pláne](script.php?id=79&s=paralelizmus-v-plane-distribute-repartition-a-gather-streams), [cost threshold, MAXDOP](script.php?id=93&s=paralelizmus-cost-threshold-maxdop-a-cxpacket-cxconsumer) | | [SOS_SCHEDULER_YIELD](waits.php#SOS_SCHEDULER_YIELD) | dotaz veľa počíta (CPU) a strieda sa s inými | [RBAR](script.php?id=94&s=rbar-kurzory-cykly-a-funkcie-po-riadkoch-v-plane), [Funkcie](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie), [Hash Match](script.php?id=73&s=hash-match-hash-join-a-hash-aggregate-build-a-probe) | | [LCK_M_S](waits.php#LCK_M_S), [LCK_M_X](waits.php#LCK_M_X)… | čakanie na inú session – **plán nie je príčina** | súbeh transakcií, [Otvorené transakcie](script.php?id=15&s=otvorene-transakcie-kto-ich-drzi-a-ako-dlho) | | [ASYNC_NETWORK_IO](waits.php#ASYNC_NETWORK_IO) | klient preberá výsledok pomaly | menej riadkov / stĺpcov do klienta | | [WRITELOG](waits.php#WRITELOG) | čakanie na zápis transakčného logu pri commit | [INSERT / UPDATE / DELETE](script.php?id=82&s=insert-update-a-delete-v-plane-narrow-vs-wide-plan-assert) (dávky) | - WaitStats v pláne obsahuje len **najvýznamnejšie** čakania dotazu, nie všetky. Na celý server použi [Wait stats – na čo server čaká](script.php?id=6&s=wait-stats-na-co-server-caka). - Čakania v pláne sú za **jedno vykonanie** (to, z ktorého je skutočný plán). Pri inom behu môžu byť iné (studená cache, iná záťaž). - Live: čakanie bežiaceho dotazu ukáže `sys.dm_exec_requests.wait_type` alebo [Aktuálne čakania na úrovni taskov](script.php?id=17&s=aktualne-cakania-na-urovni-taskov); čakania session od jej začiatku `sys.dm_exec_session_wait_stats` (2016+). ## Kedy je to v poriadku / kedy problém | V poriadku | Problém | |---|---| | elapsed ≈ CPU (dotaz pracuje, nečaká) | elapsed ≫ CPU a čakanie súvisí s plánom (I/O, grant) | | PAGEIOLATCH pri prvom behu so studenou cache | PAGEIOLATCH pri každom behu (stále sa číta priveľa) | | | LCK_M_* – rieš transakcie, nie index | ## Ako si to vyskúšať ```sql USE PlanLab; -- 1) Studená cache len pre test (DBCC DROPCLEANBUFFERS čistí buffer pool CELÉHO servera – NIKDY na produkcii!) -- CHECKPOINT; DBCC DROPCLEANBUFFERS; SELECT COUNT(*), SUM(Amount) FROM dbo.Orders WHERE Note = 'expres'; -- pozri WaitStats: PAGEIOLATCH_SH -- 2) Čakanie na inú session: okno A drží zmenený riadok, okno B ho číta -- okno A: BEGIN TRAN; UPDATE dbo.Orders SET Amount = Amount WHERE OrderID = 10; -- okno B: SELECT Amount FROM dbo.Orders WHERE OrderID = 10; -- čaká (LCK_M_S) -- okno A: ROLLBACK; → okno B dobehne; v jeho skutočnom pláne je LCK_M_S vo WaitStats -- 3) Čakania tejto session od jej začiatku (2016+) SELECT wait_type, waiting_tasks_count, wait_time_ms FROM sys.dm_exec_session_wait_stats WHERE session_id = @@SPID ORDER BY wait_time_ms DESC; ``` Spusti s **Include Actual Execution Plan** (Ctrl+M) a na SELECT otvor F4 → *WaitStats* a *QueryTimeStats*. Bod 1 s DBCC DROPCLEANBUFFERS rob len na vlastnom testovacom serveri. ## Čo s tým 1. Najprv porovnaj **CPU a elapsed** – rozhodne, či ladiť prácu (plán) alebo čakanie. 2. Čakanie súvisiace s plánom (I/O, grant, paralelizmus) → recept z tabuľky vyššie. 3. Čakanie mimo plánu (LCK_M_*, ASYNC_NETWORK_IO, WRITELOG) → transakcie, aplikácia, disk logu. 4. Vždy over na celom serveri: [Wait stats – rozdiel za N sekúnd](script.php?id=49&s=wait-stats-rozdiel-za-n-sekund), [Server je pomalý – prvých 10 minút](script.php?id=59&s=server-je-pomaly-prvych-10-minut). ## Súvisiace - [Čakania – vysvetlenie typov](waits.php) - [Wait stats – na čo server čaká](script.php?id=6&s=wait-stats-na-co-server-caka) - [Aktuálne čakania na úrovni taskov](script.php?id=17&s=aktualne-cakania-na-urovni-taskov) - [Exekučné plány – kuchárka](script.php?id=64&s=exekucne-plany-kucharka-zacni-tu) - [Memory grant](script.php?id=91&s=memory-grant-kolko-pamate-dostal-dotaz-privela-alebo-primalo) ## Zdroje - [Microsoft Learn – sys.dm_os_wait_stats](https://learn.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-os-wait-stats-transact-sql) - [Microsoft Learn – Display an Actual Execution Plan](https://learn.microsoft.com/sql/relational-databases/performance/display-an-actual-execution-plan) - [Brent Ozar – blog a nástroje First Responder Kit](https://www.brentozar.com/) - [Erik Darling – blog (plány, memory grants, parameter sniffing)](https://erikdarling.com/) _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._
Plán a čakania – WaitStats a QueryTimeStats v skutočnom pláne
Čakania priamo v exekučnom pláne: WaitStats a QueryTimeStats (CPU vs. elapsed) na SELECT, ktoré čakania ukazujú na plán (PAGEIOLATCH, RESOURCE_SEMAPHORE, CXPACKET) a ktoré nie.