> [!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

So skutočným plánom v SSMS dostaneš pri kurzore alebo cykle **desiatky až tisíce plánov** – jeden za každý príkaz v každej iterácii (SSMS ich nakoniec prestane zobrazovať). V plan cache / Query Store vidíš malý dotaz s obrovským *execution_count*. Pri skalárnej funkcii je práca skrytá v Compute Scalar ([Funkcie](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie)).
## Čo to znamená
**RBAR** (*row by agonizing row*) = spracovanie dát **po jednom riadku**: kurzor, `WHILE` cyklus, skalárna funkcia volaná pre každý riadok, aplikácia volajúca procedúru pre každý záznam. Každý malý príkaz má réžiu (vyhľadanie, zápis do logu, komunikácia), ktorá sa znásobí počtom riadkov. Relačná databáza je stavaná na **množinové** (set-based) operácie – jeden príkaz nad všetkými riadkami.
### Do hĺbky
- Kurzor s predvolenými voľbami je drahší ako treba; ak musí byť, `LOCAL FAST_FORWARD` (len dopredu, len na čítanie).
- Cyklus s `TOP (1)` / `MIN(id)` v každom kroku často opakovane číta tú istú tabuľku.
- Výkon jedného malého plánu vyzerá skvele – problém je v **počte vykonaní**. Preto ho odhalí skôr [Top 20 dotazov podľa CPU](script.php?id=5&s=top-20-dotazov-podla-cpu) (execution_count, total_worker_time) než pohľad na jeden plán.
- Niektoré úlohy sa po riadkoch robiť **majú**: dávkovanie veľkých zmien (cyklus po 10 000 riadkoch je set-based v dávkach), volanie externých procedúr.
## Kedy je to v poriadku / kedy problém
| V poriadku | Problém |
|---|---|
| cyklus po dávkach (tisíce riadkov naraz) | cyklus po jednom riadku nad tisíckami riadkov |
| administratívne skripty nad pár objektmi | kurzor v často volanej procedúre |
| | skalárna funkcia s dotazom v SELECT zozname veľkého reportu |
## Ako si to vyskúšať
```sql
USE PlanLab;
SET STATISTICS TIME ON; -- plán NEzapínaj (vznikli by tisíce plánov)
-- 1) RBAR: kurzor cez 20 000 zákazníkov
DECLARE @id int, @cnt int;
DECLARE c CURSOR LOCAL FAST_FORWARD FOR SELECT CustomerID FROM dbo.Customers;
DROP TABLE IF EXISTS #r;
CREATE TABLE #r (CustomerID int PRIMARY KEY, Cnt int);
OPEN c;
FETCH NEXT FROM c INTO @id;
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @cnt = COUNT(*) FROM dbo.Orders WHERE CustomerID = @id;
INSERT #r VALUES (@id, @cnt);
FETCH NEXT FROM c INTO @id;
END;
CLOSE c; DEALLOCATE c;
-- 2) Set-based: to isté jedným príkazom
DROP TABLE IF EXISTS #s;
SELECT c.CustomerID, COUNT(o.OrderID) AS Cnt INTO #s
FROM dbo.Customers AS c LEFT JOIN dbo.Orders AS o ON o.CustomerID = c.CustomerID
GROUP BY c.CustomerID;
```
Porovnaj v *Messages* súčet časov. Skutočný plán zapni až pre bod 2 (Ctrl+M) – je to jeden plán s Hash Match / Stream Aggregate.
## Čo s tým
1. Nájdi RBAR podľa **počtu vykonaní** v cache / Query Store, nie podľa jedného plánu.
2. Prepíš na jeden príkaz: `INSERT … SELECT`, `UPDATE … FROM … JOIN`, `MERGE` (opatrne), window funkcie namiesto „predchádzajúceho riadku“ v cykle.
3. Ak je spracovanie po častiach nutné, rob ho po **dávkach** (TOP (n) + kľúč), nie po riadkoch.
4. Skalárne funkcie: inlining (2019+) alebo prepis na inline TVF ([Funkcie v pláne](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie)).
## Súvisiace
- [Funkcie v pláne](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie)
- [Window funkcie v pláne](script.php?id=80&s=window-funkcie-v-plane-segment-sequence-project-a-window-spool)
- [Top 20 dotazov podľa CPU](script.php?id=5&s=top-20-dotazov-podla-cpu)
- [Najdrahšie stored procedures](script.php?id=30&s=najdrahsie-stored-procedures-plan-cache)
## Zdroje
- [Microsoft Learn – DECLARE CURSOR](https://learn.microsoft.com/sql/t-sql/language-elements/declare-cursor-transact-sql)
- [Microsoft Learn – Scalar UDF inlining](https://learn.microsoft.com/sql/relational-databases/user-defined-functions/scalar-udf-inlining)
- [Brent Ozar – blog a nástroje First Responder Kit](https://www.brentozar.com/)
- [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/)
_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._RBAR – kurzory, cykly a funkcie po riadkoch v pláne
Spracovanie po riadkoch (RBAR) cez kurzor, WHILE cyklus alebo skalárnu funkciu: ako sa prejaví v plánoch a plan cache, prečo je pomalé a ako ho prepísať na set-based príkaz alebo dávky.