> [!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  Pri table variable (`@t`) vidíš sken s *Estimated Number of Rows* = **1** (pred SQL Server 2019) a skutočnosť v tisíckach. Nasleduje typicky Nested Loops so 50 000 vykonaniami. ## Čo to znamená **Table variable** (`DECLARE @t TABLE`) nemá štatistiky a dotaz s ňou sa kompiluje skôr, než sa naplní. Optimalizátor preto do SQL Server 2017 predpokladá **1 riadok**. **#temp tabuľka** je obyčajná tabuľka v tempdb – má štatistiky, odhad je presný a pri veľkej zmene obsahu sa dotaz rekompiluje. ### Do hĺbky - **Table variable deferred compilation** (SQL Server 2019+, compat 150): príkaz s table variable sa skompiluje až pri prvom vykonaní, takže použije **skutočný počet riadkov** z prvého behu. Stále však nepozná **rozdelenie hodnôt** (štatistiky stĺpcov) a ďalšie spustenia použijú ten istý plán. - `OPTION (RECOMPILE)` na príkaze s table variable dá optimalizátoru aktuálny počet riadkov aj v starších verziách. - Table variable nespôsobuje rekompilácie a pri malých počtoch riadkov (desiatky) je úplne v poriadku. - Modifikácia table variable (INSERT … SELECT do @t) nemôže bežať paralelne; čítanie z nej áno. - #temp tabuľka sa dá indexovať aj po vytvorení a má štatistiky – vhodná pre medzivýsledky so stovkami a viac riadkov. ## Kedy je to v poriadku / kedy problém | V poriadku | Problém | |---|---| | desiatky riadkov, jednoduché použitie | tisíce riadkov a spojenie s veľkou tabuľkou | | 2019+ a stabilný počet riadkov | počet riadkov sa medzi volaniami veľmi mení | | #temp pre veľké medzivýsledky | Nested Loops s tisíckami vykonaní za table variable | ## Ako si to vyskúšať ```sql USE PlanLab; ALTER DATABASE PlanLab SET COMPATIBILITY_LEVEL = 140; -- správanie pred 2019 GO DECLARE @t TABLE (OrderID int PRIMARY KEY); INSERT @t SELECT TOP (50000) OrderID FROM dbo.Orders WHERE CustomerID = 1; SELECT COUNT(*) FROM @t AS t JOIN dbo.OrderLines AS l ON l.OrderID = t.OrderID; -- odhad 1 GO CREATE TABLE #t (OrderID int PRIMARY KEY); INSERT #t SELECT TOP (50000) OrderID FROM dbo.Orders WHERE CustomerID = 1; SELECT COUNT(*) FROM #t AS t JOIN dbo.OrderLines AS l ON l.OrderID = t.OrderID; -- odhad 50 000 DROP TABLE #t; GO ALTER DATABASE PlanLab SET COMPATIBILITY_LEVEL = 150; -- 2019+: deferred compilation (ak to server podporuje) GO DECLARE @t TABLE (OrderID int PRIMARY KEY); INSERT @t SELECT TOP (50000) OrderID FROM dbo.Orders WHERE CustomerID = 1; SELECT COUNT(*) FROM @t AS t JOIN dbo.OrderLines AS l ON l.OrderID = t.OrderID; -- odhad 50 000 ``` Spusti s **Include Actual Execution Plan** (Ctrl+M) a porovnaj odhad pri skene `@t` / `#t` a zvolené spojenie. Compat level potom vráť na pôvodnú hodnotu. ## Čo s tým 1. Medzivýsledky so stovkami a viac riadkov ukladaj do **#temp** tabuliek. 2. Ak musí ostať table variable: `OPTION (RECOMPILE)` na príkaze, ktorý ju číta, alebo SQL Server 2019+ s compat 150. 3. Na 2019+ pri veľmi premenlivom počte riadkov pomôže tiež RECOMPILE – deferred compilation platí len pre prvé spustenie. ## Súvisiace - [Zlé odhady riadkov](script.php?id=84&s=zle-odhady-riadkov-odhad-vs-skutocnost-a-statistiky) - [Nested Loops](script.php?id=71&s=nested-loops-vnorene-cykly-outer-a-inner-vstup) - [Funkcie v pláne (MSTVF)](script.php?id=83&s=funkcie-v-plane-scalar-udf-inlining-2019-a-table-valued-funkcie) - [Kto spotrebúva tempdb](script.php?id=20&s=kto-spotrebuva-tempdb) ## Zdroje - [Microsoft Learn – table (Transact-SQL)](https://learn.microsoft.com/sql/t-sql/data-types/table-transact-sql) - [Microsoft Learn – Intelligent query processing details](https://learn.microsoft.com/sql/relational-databases/performance/intelligent-query-processing-details) - [Microsoft Learn – Intelligent query processing](https://learn.microsoft.com/sql/relational-databases/performance/intelligent-query-processing) - [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._
Table variable vs. #temp tabuľka – odhady a deferred compilation (2019+)
Prečo table variable odhaduje 1 riadok, čo zmenila table variable deferred compilation v SQL Server 2019 (compat 150), kedy použiť #temp tabuľku a OPTION (RECOMPILE).