Preskočiť na obsah
Návod

Exekučné plány – kuchárka (začni tu)

Ako čítať exekučný plán SQL Servera od základov: odhadovaný vs. skutočný plán, smer čítania, šípky, percentá, okno Properties, varovania, mapa „vidím X → recept“ a postup pri pomalom dotaze.

17 min čítania 10 krokov 4 obrázky SQL Server 2016+
> [!TIP]
> Začni tu. Za 15–20 minút budeš vedieť plán otvoriť, prečítať a nájsť podozrivé miesto. Špecifiká (operátory, varovania, typické problémy) sú v **krátkych receptoch** – každý má jednu tému, obrázok, ukážku na vyskúšanie a „čo s tým“. Mapa receptov je [nižšie](#mapa-vidim-x-v-plane-chod-na-recept).
> Ukážky na vyskúšanie bežia v malej testovacej databáze [PlanLab](script.php?id=65&s=planlab-testovacia-databaza-pre-recepty-exekucnych-planov) – vytvor si ju ako prvú.

## Čo je exekučný plán

Keď pošleš dotaz, SQL Server ho najprv **neskúša vykonať**, ale vymyslí postup – **exekučný plán**. Plán je strom **operátorov** (čítaj index, spoj dva vstupy, zoraď, spočítaj…), ktoré si podávajú riadky.

Postup vyberá **optimalizátor**. Je to *cost-based* optimalizátor: pre niekoľko variantov odhadne **náklady** (CPU + I/O podľa vnútorného modelu) a vyberie najlacnejší, ktorý stihol nájsť. Kľúčové je slovo **odhad**: optimalizátor nevie, koľko riadkov naozaj príde. Počty riadkov (tzv. *cardinality*) odhaduje zo **štatistík** – histogramu hodnôt v stĺpci. Keď je odhad zlý, aj „najlacnejší“ plán je zlý. Väčšina problémov s výkonom sa dá vystopovať k miestu, kde sa odhad rozišiel so skutočnosťou.

![Od dotazu cez optimalizátor k plánu a jeho vykonaniu](uploads/2026/11/plan-g0-flow.svg "Optimalizátor odhaduje zo štatistík, plán sa uloží do cache, skutočné čísla vznikajú až pri vykonaní")

Hotový plán sa uloží do **plan cache** a ďalšie spustenie rovnakého dotazu ho použije znova (bez novej optimalizácie). To šetrí CPU, ale znamená to aj, že plán vytvorený pre jednu hodnotu parametra sa použije aj pre iné – viď [Parameter sniffing](script.php?id=87&s=parameter-sniffing-jeden-plan-pre-rozne-hodnoty-psp-2022-oppo-2025).

Optimalizátor nehľadá donekonečna. Pri jednoduchých dotazoch vyberie **trivial plan** (Optimization Level = `TRIVIAL`), pri ostatných skúša, kým nenájde „dosť dobrý“ plán alebo kým mu nevyprší čas (vlastnosť *Reason For Early Termination*: `Good Enough Plan Found`, `Time Out`, `Memory Limit Exceeded`).

## Odhadovaný vs. skutočný plán

| | Odhadovaný plán (*estimated*) | Skutočný plán (*actual*) |
|---|---|---|
| Dotaz sa spustí? | nie | áno (a vráti dáta) |
| Čo obsahuje | tvar plánu, odhady riadkov a nákladov | to isté + skutočné počty riadkov, vykonaní, čas, pamäť, čakania, varovania z behu |
| Kedy použiť | dotaz beží hodiny, mení dáta, alebo chceš len vidieť tvar | vždy, keď sa dá – len tu vidíš rozdiel odhad / skutočnosť |
| SSMS | **Ctrl+L** (Display Estimated Execution Plan) | **Ctrl+M** (Include Actual Execution Plan), potom spusti |

Skutočný plán **nie je iný plán** – je to ten istý plán (ktorý bol vybraný pre toto spustenie) doplnený o čísla z behu. Percentá nákladov v ňom ostávajú **odhadované** (viď nižšie).

Ďalšie možnosti:

- **Live Query Statistics** – v SSMS tlačidlo *Include Live Query Statistics*: počas behu vidíš, ako riadky pribúdajú a ktorý operátor práve pracuje. Hodí sa na dotazy, ktoré nikdy nedobehnú.
- **Lightweight profiling** – lacný zber runtime štatistík. Od SQL Server 2019 je zapnutý predvolene (`LIGHTWEIGHT_QUERY_PROFILING`), v 2016 SP1 / 2017 cez trace flag 7412. Vďaka nemu ide pozrieť plán bežiaceho dotazu cez `sys.dm_exec_query_statistics_xml`.
- **Posledný skutočný plán** (SQL Server 2019+) – po zapnutí `ALTER DATABASE SCOPED CONFIGURATION SET LAST_QUERY_PLAN_STATS = ON` vráti `sys.dm_exec_query_plan_stats` ekvivalent posledného skutočného plánu z cache – bez opätovného spustenia dotazu.

Podrobne v recepte [Ako získať exekučný plán](script.php?id=66&s=ako-ziskat-exekucny-plan-ssms-plan-cache-query-store-extended-events).

## Ako plán získať (rýchly prehľad)

| Odkiaľ | Typ | Ako |
|---|---|---|
| SSMS | odhadovaný / skutočný | Ctrl+L / Ctrl+M |
| T-SQL relácia | odhadovaný | `SET SHOWPLAN_XML ON` (dotaz sa nevykoná) |
| T-SQL relácia | skutočný | `SET STATISTICS XML ON` (alebo textovo `SET STATISTICS PROFILE ON`) |
| Plan cache | odhadovaný | `sys.dm_exec_query_stats` + `sys.dm_exec_query_plan(plan_handle)` |
| Plan cache, 2019+ | posledný skutočný | `sys.dm_exec_query_plan_stats(plan_handle)` |
| Bežiaci dotaz | živý | `sys.dm_exec_query_statistics_xml(session_id)` |
| Query Store | odhadovaný (história) | `sys.query_store_plan.query_plan` |
| Extended Events | skutočný | `query_post_execution_plan_profile` (lacnejší) / `query_post_execution_showplan` (drahý) |

Plán ulož cez pravý klik → **Save Execution Plan As…** ako súbor `.sqlplan` – je to obyčajné XML, ktoré sa dá poslať kolegovi, otvoriť v SSMS alebo v nástroji Plan Explorer ([Výbava](vybava.php#komunita)). Pravý klik → **Show Execution Plan XML…** ukáže surové XML; hodí sa na hľadanie (Ctrl+F) vlastností, ktoré grafika skrýva.

## Ako plán čítať: smer, šípky, percentá

![Výrez plánu: SELECT, Nested Loops, Index Seek a Key Lookup s poradím čítania](uploads/2026/11/plan-g0-read.svg "Dáta tečú sprava doľava, logika (GetNext) začína vľavo")

**Smer.** Plán sa kreslí ako strom, koreň (`SELECT`, `INSERT`…) je **vľavo hore**. Operátory sú *iterátory*: ľavý operátor si od pravého pýta „daj mi ďalší riadok“ (*GetNext*). Logika teda ide **zľava doprava**, dáta tečú **sprava doľava**. Pre začiatok čítaj **sprava doľava a zhora nadol** – tak, ako dáta vznikajú: najprv odkiaľ sa číta (indexy, tabuľky), potom ako sa spájajú, zoraďujú a počítajú.

**Šípky.** Hrúbka šípky naznačuje počet riadkov, ktoré tečú medzi operátormi (v skutočnom pláne podľa skutočného počtu). Prekvapivo hrubá šípka hlboko v pláne, ktorá sa neskôr zúži na pár riadkov, je typické miesto na zlepšenie – filtruje sa príliš neskoro. Prejdi myšou nad šípkou: tooltip ukáže odhad aj skutočnosť.

**Percentá (cost).** Číslo pod operátorom je **odhadovaný** podiel na nákladoch celého plánu – **aj v skutočnom pláne**. Nie je to čas ani skutočná práca. Ak bol odhad riadkov zlý, percentá klamú: operátor s 2 % môže v skutočnosti trvať najdlhšie. Ber ich ako „kam sa pozrieť najskôr“, nie ako dôkaz.

**Čas operátorov.** Skutočný plán má pri operátoroch vlastnosť *Actual Time Statistics* (a SSMS ukazuje čas pod ikonou). Pozor: v **row mode** čas operátora zahŕňa aj čas operátorov napravo od neho (jeho detí), v **batch mode** je to len jeho vlastný čas.

## Okno Properties (F4) – kde je pravda

Tooltip je len výťah. Klikni na operátor a stlač **F4** – okno *Properties* ukáže všetko. Najdôležitejšie:

![Okno Properties operátora Index Seek](uploads/2026/11/plan-g0-op.svg "Properties (F4): odhad vs. skutočnosť, Rows Read, Seek Predicates a Predicate")

| Vlastnosť | Čo hovorí | Na čo pozor |
|---|---|---|
| Physical / Logical Operation | čo operátor robí (napr. Hash Match / Inner Join) | |
| Estimated Number of Rows **Per Execution** | odhad riadkov na jedno vykonanie | porovnávaj s Actual ÷ Number of Executions |
| Actual Number of Rows **for All Executions** | skutočný súčet za všetky vykonania | rozdiel 10× a viac = podozrivé |
| Number of Executions | koľkokrát operátor bežal (vnútorná strana Nested Loops beží opakovane) | tisíce vykonaní = tisíce malých čítaní |
| Number of Rows Read | koľko riadkov operátor prečítal (aj tie, čo neprešli) | ≫ Actual Rows → filter až po prečítaní |
| Seek Predicates | podmienka, ktorou index **hľadá** | dobré – čítajú sa len potrebné riadky |
| Predicate | podmienka, ktorou sa **filtruje po prečítaní** (residual) | veľa prečítaných, málo vrátených |
| Output List | stĺpce, ktoré operátor posiela ďalej | pri Key Lookup = chýbajúce stĺpce v indexe |
| Estimated Execution Mode / Actual Execution Mode | Row alebo Batch | batch mode = columnstore / 2019+ |
| Warnings | varovania z kompilácie aj behu | spill, konverzia, chýbajúce štatistiky… |

## Koreňový operátor SELECT – vlastnosti celého dotazu

Klikni na úplne ľavý operátor (`SELECT`, `INSERT`…) a stlač F4. Tu sú informácie za celý dotaz:

![Okno Properties koreňového operátora SELECT](uploads/2026/11/plan-g0-root.svg "Koreň plánu: pamäť, časy, čakania a hodnoty parametrov celého dotazu")

- **CompileTime / CompileCPU / CompileMemory** – koľko stála optimalizácia. Dotaz, ktorý sa kompiluje pri každom spustení (napr. `OPTION (RECOMPILE)`), platí túto cenu vždy.
- **Memory Grant Info** – koľko pamäte dotaz pýtal (*RequestedMemory*), dostal (*GrantedMemory*) a reálne využil (*MaxUsedMemory*); *GrantWaitTime* = koľko čakal na pridelenie. Viď [Memory grant](script.php?id=91&s=memory-grant-kolko-pamate-dostal-dotaz-privela-alebo-primalo).
- **QueryTimeStats** – *CpuTime* a *ElapsedTime* celého dotazu. Ak je elapsed oveľa väčší ako CPU, dotaz väčšinu času **čakal**.
- **WaitStats** – na čo dotaz čakal (najväčšie čakania). Prepojenie na [Čakania](waits.php) je v recepte [Plán a čakania](script.php?id=97&s=plan-a-cakania-waitstats-a-querytimestats-v-skutocnom-plane).
- **Parameter List** – pri každom parametri *Parameter Compiled Value* (pre akú hodnotu sa plán vytvoril) a v skutočnom pláne aj *Parameter Runtime Value* (s akou hodnotou bežal teraz). Rôzne hodnoty = podozrenie na [parameter sniffing](script.php?id=87&s=parameter-sniffing-jeden-plan-pre-rozne-hodnoty-psp-2022-oppo-2025).
- **Optimization Level** (`TRIVIAL` / `FULL`) a **Reason For Early Termination Of Statement Optimization** – prečo optimalizátor skončil.
- **CardinalityEstimationModelVersion** – verzia odhadovača (70 = legacy, 120+ = nový). Viď [Cardinality estimator](script.php?id=85&s=cardinality-estimator-ce-70-vs-120-a-compat-level).
- **Degree of Parallelism** a **NonParallelPlanReason** – koľko vlákien, prípadne prečo plán nemohol byť paralelný.
- **OptimizerStatsUsage** – ktoré štatistiky optimalizátor použil a kedy boli naposledy aktualizované.
- **Set Options**, **QueryHash / QueryPlanHash**, **RetrievedFromCache** – detaily na porovnávanie a hľadanie v cache.

## Varovania v pláne

**Žltý trojuholník s výkričníkom** pri operátore (alebo pri SELECT) = varovanie. Niektoré vznikajú pri kompilácii (implicitná konverzia, chýbajúce štatistiky, chýbajúci predikát spojenia), iné až počas behu (spill do tempdb, nadmerný memory grant) – tie uvidíš len v skutočnom pláne. Text varovania je vo vlastnosti **Warnings** (F4). Katalóg s vysvetlením je v recepte [Varovania v pláne](script.php?id=96&s=varovania-v-plane-zlty-trojuholnik-no-join-predicate-no-statistics).

Ďalšie značky: **žlté koliesko s dvoma šípkami** pri ikone = operátor beží paralelne ([Paralelizmus v pláne](script.php?id=79&s=paralelizmus-v-plane-distribute-repartition-a-gather-streams)); **zelený text „Missing Index“** nad plánom = návrh indexu od optimalizátora ([Chýbajúci index v pláne](script.php?id=92&s=chybajuci-index-v-plane-zeleny-text-preco-ho-nebrat-naslepo)) – nie príkaz, len nápad.

## SET STATISTICS IO, TIME – čísla vedľa plánu

Plán hovorí *ako*, štatistiky hovoria *koľko*. Pred dotaz daj:

```sql
SET STATISTICS IO, TIME ON;
```

V záložke *Messages* uvidíš pre každú tabuľku **logical reads** (8 KB stránky čítané z pamäte) a pre dotaz **CPU time** a **elapsed time**. Logical reads sú najlepšie číslo na porovnanie „pred zmenou / po zmene“ – menej závisia od toho, čo je práve v cache. Podrobne v recepte [SET STATISTICS IO, TIME](script.php?id=67&s=set-statistics-io-time-citanie-vystupu-vedla-planu).

## Mapa: vidím X v pláne → choď na recept

| Vidím v pláne | Recept |
|---|---|
| Table Scan / Clustered Index Scan na veľkej tabuľke | [Table Scan a Clustered Index Scan](script.php?id=68&s=table-scan-a-clustered-index-scan-citanie-celej-tabulky) |
| Index Seek, ale *Predicate* a veľa *Rows Read* | [Index Seek – seek vs. residual predicate](script.php?id=69&s=index-seek-seek-predicate-vs-residual-predicate) |
| Key Lookup / RID Lookup s tisíckami vykonaní | [Key Lookup a RID Lookup](script.php?id=70&s=key-lookup-a-rid-lookup-dohladanie-chybajucich-stlpcov) |
| Nested Loops, vnútorná strana beží veľa krát | [Nested Loops](script.php?id=71&s=nested-loops-vnorene-cykly-outer-a-inner-vstup) |
| Merge Join, pred ním Sort | [Merge Join](script.php?id=72&s=merge-join-spajanie-zoradenych-vstupov) |
| Hash Match (join alebo aggregate) | [Hash Match](script.php?id=73&s=hash-match-hash-join-a-hash-aggregate-build-a-probe) |
| Adaptive Join | [Adaptive Join](script.php?id=74&s=adaptive-join-hash-match-alebo-nested-loops-az-za-behu-2017) |
| Sort, Top N Sort, Top | [Sort, Top a Top N Sort](script.php?id=75&s=sort-top-a-top-n-sort-zoradovanie-a-pamat) |
| Stream Aggregate vs. Hash Aggregate | [Stream Aggregate vs. Hash Aggregate](script.php?id=76&s=stream-aggregate-vs-hash-aggregate-group-by-v-plane) |
| Compute Scalar, Filter, Constant Scan, Concatenation | [Malé operátory](script.php?id=77&s=compute-scalar-filter-constant-scan-a-concatenation-male-operatory) |
| Table / Index / Row Count / Window Spool | [Spools](script.php?id=78&s=spools-table-index-row-count-a-window-spool-eager-vs-lazy) |
| Gather / Repartition / Distribute Streams | [Paralelizmus v pláne](script.php?id=79&s=paralelizmus-v-plane-distribute-repartition-a-gather-streams) |
| Segment, Sequence Project, Window Spool | [Window funkcie v pláne](script.php?id=80&s=window-funkcie-v-plane-segment-sequence-project-a-window-spool) |
| Columnstore Index Scan, Actual Execution Mode = Batch | [Columnstore a batch mode](script.php?id=81&s=columnstore-a-batch-mode-actual-execution-mode-segment-elimination) |
| Clustered Index Insert / Update / Delete, Split, Assert | [INSERT / UPDATE / DELETE v pláne](script.php?id=82&s=insert-update-a-delete-v-plane-narrow-vs-wide-plan-assert) |
| UDF, Table Valued Function, „skrytá“ práca | [Funkcie v pláne](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie) |
| Odhad 10, skutočnosť 100 000 | [Zlé odhady riadkov](script.php?id=84&s=zle-odhady-riadkov-odhad-vs-skutocnost-a-statistiky) |
| Iný plán po zmene compat levelu | [Cardinality estimator](script.php?id=85&s=cardinality-estimator-ce-70-vs-120-a-compat-level) |
| Table variable s odhadom 1 riadok | [Table variable vs. #temp](script.php?id=86&s=table-variable-vs-temp-tabulka-odhady-a-deferred-compilation-2019) |
| Compiled value ≠ Runtime value | [Parameter sniffing](script.php?id=87&s=parameter-sniffing-jeden-plan-pre-rozne-hodnoty-psp-2022-oppo-2025) |
| CONVERT_IMPLICIT, varovanie o konverzii | [Implicitná konverzia](script.php?id=88&s=implicitna-konverzia-convert-implicit-varchar-vs-nvarchar) |
| Funkcia na stĺpci vo WHERE, LIKE '%…' | [Non-SARGable podmienky](script.php?id=89&s=non-sargable-podmienky-funkcia-na-stlpci-like-x-or) |
| Sort Warning / Hash Warning, spill | [Spill do tempdb](script.php?id=90&s=spill-do-tempdb-sort-a-hash-warning-memory-grant-feedback) |
| Excessive Grant, GrantWaitTime | [Memory grant](script.php?id=91&s=memory-grant-kolko-pamate-dostal-dotaz-privela-alebo-primalo) |
| Zelený text „Missing Index“ | [Chýbajúci index v pláne](script.php?id=92&s=chybajuci-index-v-plane-zeleny-text-preco-ho-nebrat-naslepo) |
| Paralelizmus pri malom dotaze, CXPACKET | [Paralelizmus – cost threshold, MAXDOP](script.php?id=93&s=paralelizmus-cost-threshold-maxdop-a-cxpacket-cxconsumer) |
| Tisíce rovnakých malých plánov, kurzor | [RBAR – kurzory a cykly](script.php?id=94&s=rbar-kurzory-cykly-a-funkcie-po-riadkoch-v-plane) |
| Dotaz včera rýchly, dnes pomalý | [Plan regression a Query Store](script.php?id=95&s=plan-regression-novy-horsi-plan-a-vynutenie-cez-query-store) |
| Iné varovanie (No Join Predicate, No Statistics…) | [Varovania v pláne](script.php?id=96&s=varovania-v-plane-zlty-trojuholnik-no-join-predicate-no-statistics) |
| WaitStats v pláne, elapsed ≫ CPU | [Plán a čakania](script.php?id=97&s=plan-a-cakania-waitstats-a-querytimestats-v-skutocnom-plane) |

## Postup: mám pomalý dotaz

1. **Zmeraj.** Spusti dotaz s `SET STATISTICS IO, TIME ON` a so skutočným plánom (Ctrl+M). Ak sa nedá spustiť, vezmi posledný skutočný plán (2019+), plán z Query Store alebo aspoň odhadovaný plán.
2. **Pozri koreň (SELECT, F4).** Varovania, *QueryTimeStats* (CPU vs. elapsed), *WaitStats*, *Memory Grant Info*, *Parameter List* (compiled vs. runtime), *Degree of Parallelism*.
3. **Čaká, alebo pracuje?** Elapsed ≫ CPU → dotaz čaká. Ak čaká na iné session (`LCK_M_*`), problém nie je v pláne – [Plán a čakania](script.php?id=97&s=plan-a-cakania-waitstats-a-querytimestats-v-skutocnom-plane).
4. **Varovania.** Nájdi žlté trojuholníky – spill, konverzia, chýbajúce štatistiky sú konkrétne stopy.
5. **Odhad vs. skutočnosť.** Choď sprava doľava a hľadaj **prvý** operátor, kde sa odhad a skutočnosť líšia 10× a viac. Chyba sa odtiaľ šíri doľava – oprav príčinu tam, nie následky ďalej.
6. **Hrubé šípky a veľa vykonaní.** Kde tečie veľa riadkov, ktoré sa neskôr zahodia? Kde beží Key Lookup alebo vnútorná strana Nested Loops tisíckrát?
7. **Predicate vs. Seek Predicates.** Sken s Predicate alebo seek s veľkým *Number of Rows Read* = chýba vhodný index alebo podmienka nie je SARGable.
8. **Zmeň jednu vec.** Index, prepis podmienky, aktualizácia štatistík. Hinty až ako posledná možnosť.
9. **Over.** Znova plán + logical reads. Porovnaj (pravý klik → *Compare Showplan*). Zlepšenie musí byť vidieť v číslach, nie len v percentách.
10. **Stabilizuj.** Ak dotaz skáče medzi plánmi, pozri [Query Store](script.php?id=95&s=plan-regression-novy-horsi-plan-a-vynutenie-cez-query-store) (porovnanie a vynútenie plánu).

## Krátky slovník

- **Seek** – index sa použije na skok priamo k hľadaným hodnotám. **Scan** – prečíta sa celý index alebo tabuľka (alebo jej veľká časť).
- **Predicate (residual)** – filter aplikovaný až na prečítané riadky. **Seek Predicate** – podmienka, ktorou sa v indexe hľadá.
- **Cardinality** – (odhadovaný) počet riadkov. **Selectivity** – aký podiel riadkov podmienka prepustí.
- **Memory grant** – pamäť pridelená dotazu pred štartom na triedenie a hashovanie.
- **SARGable** – podmienka, ktorú vie index použiť na hľadanie (*Search ARGument able*).
- **Blokujúci (stop-and-go) operátor** – nevydá prvý riadok, kým nespracuje celý vstup (Sort, Hash build, eager spool).
- **Row mode / batch mode** – spracovanie po riadkoch alebo po dávkach (~900 riadkov naraz).

## Súvisiace

- [Top 20 dotazov podľa CPU](script.php?id=5&s=top-20-dotazov-podla-cpu) – ktorý dotaz má zmysel ladiť
- [Najpomalšie dotazy podľa trvania (plan cache)](script.php?id=22&s=najpomalsie-dotazy-podla-priemerneho-trvania-plan-cache)
- [Query Store – regresie](script.php?id=26&s=query-store-regresie-24-h-vs-predoslych-24-h)
- [Chýbajúce indexy – návrhy optimalizátora](script.php?id=28&s=chybajuce-indexy-navrhy-optimalizatora)
- [Štatistiky – posledný update](script.php?id=29&s=statistiky-posledny-update-a-pocet-zmien)
- [Čakania – vysvetlenie typov](waits.php)
- [Výbava: SSMS a Plan Explorer](vybava.php#klienti)

## Zdroje

- [Microsoft Learn – Display an Actual Execution Plan](https://learn.microsoft.com/sql/relational-databases/performance/display-an-actual-execution-plan)
- [Microsoft Learn – Display the Estimated Execution Plan](https://learn.microsoft.com/sql/relational-databases/performance/display-the-estimated-execution-plan)
- [Microsoft Learn – Save an Execution Plan in XML Format](https://learn.microsoft.com/sql/relational-databases/performance/save-an-execution-plan-in-xml-format)
- [Microsoft Learn – Query Processing Architecture Guide](https://learn.microsoft.com/sql/relational-databases/query-processing-architecture-guide)
- [Microsoft Learn – Showplan Logical and Physical Operators Reference](https://learn.microsoft.com/sql/relational-databases/showplan-logical-and-physical-operators-reference)
- [Microsoft Learn – Query Profiling Infrastructure](https://learn.microsoft.com/sql/relational-databases/performance/query-profiling-infrastructure)
- [Microsoft Learn – Live Query Statistics](https://learn.microsoft.com/sql/relational-databases/performance/live-query-statistics)
- [Microsoft Learn – sys.dm_exec_query_plan_stats](https://learn.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-query-plan-stats-transact-sql)
- [Microsoft Learn – SET STATISTICS IO](https://learn.microsoft.com/sql/t-sql/statements/set-statistics-io-transact-sql)
- [Grant Fritchey – SQL Server Execution Plans, 3. vydanie (Redgate, e-kniha zadarmo)](https://www.red-gate.com/simple-talk/books/sql-server-execution-plans-third-edition/)
- [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/)
- [Erik Darling – blog (plány, memory grants, parameter sniffing)](https://erikdarling.com/)
- [Brent Ozar – blog a nástroje First Responder Kit](https://www.brentozar.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._