> [!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  Štyri „malé“ operátory, ktoré vidíš skoro v každom pláne: **Compute Scalar** (výpočet výrazu), **Filter** (lievik), **Constant Scan** (riadky z konštánt) a **Concatenation** (UNION ALL). Zvyčajne majú náklad okolo 0 % – a práve preto sa ľahko prehliadnu. ## Čo to znamená - **Compute Scalar** – vypočíta nový stĺpec z výrazu (`Amount * 1.2`, `CONCAT(...)`, konverzia typu, výsledok skalárnej funkcie). Vlastnosť *Defined Values* ukáže, čo presne počíta. - **Filter** – prepustí len riadky, ktoré splnia podmienku. Objavuje sa tam, kde podmienka **nešla použiť skôr** pri čítaní (HAVING, porovnanie stĺpcov z dvoch tabuliek po spojení, výsledok funkcie). - **Constant Scan** – vyrobí riadky z konštánt (`VALUES`, `SELECT 1`), slúži ako vstup pre vloženie alebo spojenie. Ak optimalizátor zistí, že WHERE nemôže nič vrátiť (`WHERE 1 = 0`, rozpor s CHECK constraintom), celý plán je len Constant Scan bez čítania tabuľky. - **Concatenation** – výstup jedného vstupu, potom druhého (UNION ALL; pri UNION nasleduje odstránenie duplicít – Sort alebo Hash). ### Do hĺbky - Compute Scalar často len **definuje** výraz; skutočne sa vyhodnotí až neskôr, keď ho iný operátor potrebuje (*deferred evaluation*). Preto jeho náklad aj čas môžu byť zavádzajúce. - Skalárna T-SQL funkcia v Compute Scalar sa (pred SQL Server 2019 alebo bez inliningu) vykoná **pre každý riadok** a jej práca v pláne nie je vidieť – [Funkcie v pláne](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie). - **Filter so Startup Expression Predicate** – podmienka, ktorá rozhodne, či sa vetva napravo vôbec spustí (napr. `IF @p = 1` v jednom dotaze cez `OR`). Je to lacné a užitočné. - Filter „neskoro v pláne“ (vľavo) po hrubej šípke = veľa riadkov sa vyrobilo zbytočne. Hľadaj, prečo podmienka nešla do seeku ([non-SARGable](script.php?id=89&s=non-sargable-podmienky-funkcia-na-stlpci-like-x-or)). - `OR` cez rôzne stĺpce môže viesť ku Concatenation viacerých seekov (*index union*) alebo k skenu. ## Kedy je to v poriadku / kedy problém | V poriadku | Problém | |---|---| | Compute Scalar s jednoduchým výrazom | Compute Scalar so skalárnou UDF nad miliónom riadkov | | Filter po pár riadkoch | Filter, ktorý zahodí 99 % z hrubej šípky | | Constant Scan pri VALUES / prázdnom výsledku | – | | Concatenation pre UNION ALL | Concatenation + Sort (UNION) tam, kde stačí UNION ALL | ## Ako si to vyskúšať ```sql USE PlanLab; -- 1) Compute Scalar (výraz) a Filter (HAVING) SELECT CustomerID, COUNT(*) AS pocet, SUM(Amount * 1.2) AS s_dph FROM dbo.Orders WHERE CustomerID BETWEEN 2 AND 2000 GROUP BY CustomerID HAVING COUNT(*) > 20; -- 2) Constant Scan: optimalizátor vie, že nič nevráti – tabuľka sa nečíta SELECT OrderID FROM dbo.Orders WHERE 1 = 0; -- 3) Concatenation (UNION ALL) a Constant Scan (VALUES) SELECT OrderID FROM dbo.Orders WHERE OrderID <= 3000 UNION ALL SELECT v.n FROM (VALUES (-1), (-2), (-3)) AS v(n); -- 4) Filter po spojení: porovnanie stĺpcov z dvoch tabuliek SELECT o.OrderID FROM dbo.Orders AS o JOIN dbo.Customers AS c ON c.CustomerID = o.CustomerID WHERE o.OrderDate < CAST(c.CreatedAt AS date); ``` Spusti s **Include Actual Execution Plan** (Ctrl+M) a pri každom malom operátore otvor F4 – *Defined Values* (Compute Scalar), *Predicate* (Filter), *Values* (Constant Scan). ## Čo s tým 1. Filter po hrubej šípke: dostaň podmienku do WHERE v SARGable tvare, aby ju zvládol seek. 2. Compute Scalar so skalárnou funkciou: pozri [Funkcie v pláne](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie). 3. UNION vs. UNION ALL: ak duplicity nevadia (alebo nemôžu nastať), UNION ALL ušetrí Sort / Hash. ## Súvisiace - [Funkcie v pláne](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie) - [Non-SARGable podmienky](script.php?id=89&s=non-sargable-podmienky-funkcia-na-stlpci-like-x-or) - [Stream Aggregate vs. Hash Aggregate](script.php?id=76&s=stream-aggregate-vs-hash-aggregate-group-by-v-plane) ## Zdroje - [Microsoft Learn – Showplan Logical and Physical Operators Reference](https://learn.microsoft.com/sql/relational-databases/showplan-logical-and-physical-operators-reference) - [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._
Compute Scalar, Filter, Constant Scan a Concatenation – malé operátory
Malé operátory v pláne: Compute Scalar (výrazy, odložené vyhodnotenie), Filter (neskorý filter, startup predicate), Constant Scan (VALUES, prázdny výsledok) a Concatenation (UNION ALL).