> [!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: **Adaptive Join** s **tromi** vstupmi: horný je *build* vstup, prostredný je vetva pre **Hash Match**, spodný je vetva pre **Nested Loops** (vnútorná strana, typicky seek). Dostupné od **SQL Server 2017** (compat level 140) v **batch mode**.
## Čo to znamená
Optimalizátor sa nemusí vopred rozhodnúť medzi Hash Match a Nested Loops. Vloží oba varianty a za behu, keď už vie, koľko riadkov naozaj prišlo z build vstupu, vyberie: **pod prahom** Nested Loops (lacné pre málo riadkov), **nad prahom** Hash Match (lacné pre veľa riadkov). Chráni to pred zlým odhadom alebo pred parametrami s veľmi rôznym počtom riadkov.
### Do hĺbky
- **Adaptive Threshold Rows** – prah počtu riadkov z build vstupu, pri ktorom sú obe stratégie rovnako drahé.
- **Estimated Join Type** – čo by zvolil odhad; **Actual Join Type** – čo sa naozaj použilo v tomto vykonaní (len v skutočnom pláne).
- Nepoužitá vetva má 0 riadkov / 0 vykonaní. Build vstup sa číta vždy.
- Podmienky: **batch mode** (do SQL Server 2017 len s columnstore indexom v dotaze; od 2019 aj *batch mode on rowstore* pri compat level 150), spojenie typu equi-join, vnútorná strana sa dá použiť ako Nested Loops (seek).
- Adaptive join drží pamäť ako Hash Match, aj keď skončí ako Nested Loops (grant sa vyhradí vopred).
- Edícia: batch mode adaptive joins sú podľa tabuľky funkcií SQL Server 2022 len v **Enterprise** (a Developer).
- Vypnutie bez zmeny compat levelu: `ALTER DATABASE SCOPED CONFIGURATION SET BATCH_MODE_ADAPTIVE_JOINS = OFF` (2019+) alebo hint `USE HINT('DISABLE_BATCH_MODE_ADAPTIVE_JOINS')`.
## Kedy je to v poriadku / kedy problém
| V poriadku | Problém |
|---|---|
| dotaz s parametrom, ktorý raz vráti 10 a raz 100 000 riadkov | adaptive join sa neobjaví (row mode, nevhodný tvar dotazu) a plán je zafixovaný na zlú stratégiu |
| Actual Join Type sa mení podľa dát | prah je ďaleko od skutočnosti kvôli zlému odhadu a pamäť je zbytočne veľká |
## Ako si to vyskúšať
```sql
USE PlanLab;
-- SQL Server 2019+: batch mode on rowstore (Enterprise / Developer)
ALTER DATABASE PlanLab SET COMPATIBILITY_LEVEL = 150; -- alebo 160 / 170 podľa servera
GO
-- Na SQL Server 2017 (compat 140) zapne batch mode prázdny filtrovaný columnstore index (trik na test):
-- CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_Lab_Dummy ON dbo.Orders (OrderID) WHERE OrderID = -1 AND OrderID = -2;
DECLARE @sql nvarchar(max) = N'
SELECT o.OrderID, o.Amount, c.Name
FROM dbo.Orders AS o
JOIN dbo.Customers AS c ON c.CustomerID = o.CustomerID
WHERE o.OrderDate >= @od;';
EXEC sys.sp_executesql @sql, N'@od date', @od = '20261030'; -- pár stoviek riadkov → Nested Loops
EXEC sys.sp_executesql @sql, N'@od date', @od = '20230101'; -- státisíce riadkov → Hash Match
-- DROP INDEX NCCI_Lab_Dummy ON dbo.Orders; -- ak si ho vytvoril
```
Spusti s **Include Actual Execution Plan** (Ctrl+M). Pri Adaptive Join porovnaj v oboch plánoch *Actual Join Type* a počty riadkov v jednotlivých vetvách. Ak sa Adaptive Join neobjaví, optimalizátor batch mode pre takto malé tabuľky nezvolil – výsledok závisí od verzie a edície.
## Čo s tým
1. Adaptive join je pomocník, nie problém. Ak ho vidíš, dotaz je chránený pred jedným typom zlého odhadu.
2. Pri dotazoch s veľkým rozptylom počtu riadkov podľa parametra zváž SQL Server 2019+ (batch mode on rowstore) alebo columnstore – pozri aj [Parameter sniffing](script.php?id=87&s=parameter-sniffing-jeden-plan-pre-rozne-hodnoty-psp-2022-oppo-2025).
3. Ak prah nesedí so skutočnosťou, oprav odhad (štatistiky), nie adaptive join.
## Súvisiace
- [Nested Loops](script.php?id=71&s=nested-loops-vnorene-cykly-outer-a-inner-vstup)
- [Hash Match](script.php?id=73&s=hash-match-hash-join-a-hash-aggregate-build-a-probe)
- [Columnstore a batch mode](script.php?id=81&s=columnstore-a-batch-mode-actual-execution-mode-segment-elimination)
- [Parameter sniffing](script.php?id=87&s=parameter-sniffing-jeden-plan-pre-rozne-hodnoty-psp-2022-oppo-2025)
- [Cardinality estimator](script.php?id=85&s=cardinality-estimator-ce-70-vs-120-a-compat-level)
## Zdroje
- [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)
- [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._Adaptive Join – Hash Match alebo Nested Loops až za behu (2017+)
Adaptive Join v pláne: tri vstupy, Adaptive Threshold Rows, Estimated vs. Actual Join Type, podmienky (batch mode, compat level 140 / 150, edícia) a ako ho vyskúšať.