> [!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 SSMS: **Columnstore Index Scan** a pri operátoroch vlastnosti **Estimated / Actual Execution Mode = Batch**. Batch mode môže mať aj Hash Match, Sort, Window Aggregate, Adaptive Join… Od SQL Server 2019 (compat 150) sa batch mode použije aj **bez columnstore** (*batch mode on rowstore*). ## Čo to znamená **Columnstore index** ukladá dáta **po stĺpcoch** v komprimovaných segmentoch (~1 milión riadkov v *row group*). Dotaz číta len potrebné stĺpce a celé segmenty vie preskočiť podľa min/max hodnôt. **Batch mode** spracúva riadky v dávkach (rádovo stovky riadkov naraz) namiesto jedného riadku – pri analytických dotazoch nad miliónmi riadkov je to často rádovo rýchlejšie. ### Do hĺbky - **Actual Segments Read / Skipped** – koľko segmentov sa čítalo a koľko preskočilo (*segment elimination*). Funguje dobre, keď sú dáta pri načítaní zoradené podľa filtrovaného stĺpca (napr. dátumu). - **Predicate pushdown** – filter sa aplikuje už pri čítaní segmentu (vidíš ho v *Predicate* columnstore skenu, nie v samostatnom Filter). - **Aggregate pushdown** – časť agregácie sa spočíta priamo pri skene; vlastnosť *Actual Number of Locally Aggregated Rows*. - **Delta store** – nové riadky (malé dávky INSERT) čakajú v rowstore časti, kým sa neskomprimujú. Veľa riadkov v delta store = pomalší sken. - **Batch mode on rowstore** (SQL Server 2019+, compat 150) – optimalizátor ho zvolí sám podľa heuristík (veľké tabuľky, agregácie, joiny). V tabuľke funkcií SQL Server 2022 je označený ako **Enterprise** (a Developer). - Batch mode umožňuje aj [Adaptive Join](script.php?id=74&s=adaptive-join-hash-match-alebo-nested-loops-az-za-behu-2017), *Window Aggregate* ([window funkcie](script.php?id=80&s=window-funkcie-v-plane-segment-sequence-project-a-window-spool)) a memory grant feedback pre batch mode. - V batch mode je *Actual Elapsed Time* operátora jeho vlastný čas (nie súčet s deťmi ako v row mode). ## Kedy je to v poriadku / kedy problém | V poriadku | Problém | |---|---| | reporty a agregácie nad miliónmi riadkov | OLTP dotaz na jeden riadok cez columnstore (lepší je rowstore index) | | veľa Segments Skipped pri filtri na dátum | Segments Skipped = 0 napriek filtru (dáta nie sú zoradené) | | batch mode pri Hash Match a Sort | operátor v row mode medzi batch operátormi (prepínanie) | ## Ako si to vyskúšať ```sql USE PlanLab; SET STATISTICS IO, TIME ON; -- 1) Bez columnstore (row mode, ak nie je compat 150+ s batch mode on rowstore) SELECT ProductID, SUM(Qty * Price) AS trzba, COUNT(*) AS riadky FROM dbo.OrderLines GROUP BY ProductID; -- 2) Neklastrovaný columnstore index (SQL Server 2016+) CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_Lab_Lines ON dbo.OrderLines (OrderID, ProductID, Qty, Price); SELECT ProductID, SUM(Qty * Price) AS trzba, COUNT(*) AS riadky FROM dbo.OrderLines GROUP BY ProductID; -- 3) Filter na OrderID: koľko segmentov sa preskočilo? SELECT SUM(Qty) FROM dbo.OrderLines WHERE OrderID > 290000; DROP INDEX NCCI_Lab_Lines ON dbo.OrderLines; ``` Spusti s **Include Actual Execution Plan** (Ctrl+M). Pri Columnstore Index Scan a Hash Match pozri *Actual Execution Mode*, *Actual Segments Read / Skipped* a v *Messages* „segment reads“ / lob logical reads. Pri 900 000 riadkoch vzniká len jeden segment na stĺpec – pri väčších tabuľkách je segment elimination výraznejšia. ## Čo s tým 1. Analytické dotazy nad veľkými tabuľkami: neklastrovaný (OLTP + reporty) alebo klastrovaný columnstore (sklad dát). 2. Načítavaj dáta zoradené podľa najčastejšieho filtra (dátum) – zlepší segment elimination. 3. Pri SQL Server 2019+ over compat level 150+ a edíciu – batch mode on rowstore môže pomôcť aj bez columnstore. 4. Columnstore nepoužívaj na tabuľky s častými jednoriadkovými UPDATE / DELETE bez rozmyslu (delta store, fragmentácia). ## Súvisiace - [Adaptive Join](script.php?id=74&s=adaptive-join-hash-match-alebo-nested-loops-az-za-behu-2017) - [Window funkcie v pláne](script.php?id=80&s=window-funkcie-v-plane-segment-sequence-project-a-window-spool) - [Hash Match](script.php?id=73&s=hash-match-hash-join-a-hash-aggregate-build-a-probe) - [Stream Aggregate vs. Hash Aggregate](script.php?id=76&s=stream-aggregate-vs-hash-aggregate-group-by-v-plane) ## Zdroje - [Microsoft Learn – Columnstore indexes: overview](https://learn.microsoft.com/sql/relational-databases/indexes/columnstore-indexes-overview) - [Microsoft Learn – Query Processing Architecture Guide](https://learn.microsoft.com/sql/relational-databases/query-processing-architecture-guide) - [Microsoft Learn – Intelligent query processing](https://learn.microsoft.com/sql/relational-databases/performance/intelligent-query-processing) - [Microsoft Learn – Editions and supported features of SQL Server 2022](https://learn.microsoft.com/sql/sql-server/editions-and-components-of-sql-server-2022) - [Hugo Kornelis – SQL Server Execution Plan Reference (SQLServerFast)](https://sqlserverfast.com/epr/) _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._
Columnstore a batch mode – Actual Execution Mode, segment elimination
Columnstore Index Scan a batch mode v pláne: Actual Execution Mode, Segments Read / Skipped, predicate a aggregate pushdown, delta store a batch mode on rowstore (2019+).