Preskočiť na obsah
Návod

Merge Join – spájanie zoradených vstupov

Merge Join v pláne: prečo potrebuje zoradené vstupy, Sort pred spojením, one-to-many vs. many-to-many (Worktable v tempdb) a kedy je to najlepšie spojenie.

3 min čítania 3 kroky 1 obrázok SQL Server 2016+
> [!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

![Merge Join ako zips dvoch zoradených vstupov](uploads/2026/11/plan-o5.svg "Merge Join prechádza oba zoradené vstupy naraz – bez hľadania a bez hash tabuľky")

V SSMS: **Merge Join** s dvoma vstupmi. Často pred ním vidíš **Sort** na jednej alebo oboch stranách. Vlastnosť *Many to Many* hovorí, či môžu byť duplicity na oboch stranách.

## Čo to znamená

Merge Join potrebuje oba vstupy **zoradené podľa stĺpcov spojenia**. Potom ich prechádza naraz ako zips: porovná aktuálne hodnoty, pri zhode vydá riadok, pri nezhode posunie stranu s menšou hodnotou. Každý riadok sa prečíta raz, netreba hľadať ani stavať hash tabuľku. Je to výborné spojenie pre **veľké vstupy, ktoré sú už zoradené** (napr. oba podľa klastrovaného kľúča).

### Do hĺbky

- Zoradenie môže prísť „zadarmo“ z indexu (sken alebo seek v poradí kľúča – vlastnosť *Ordered = True*) alebo z explicitného **Sort**. Sort na veľkom vstupe je blokujúci, potrebuje memory grant a môže [spillovať](script.php?id=90&s=spill-do-tempdb-sort-a-hash-warning-memory-grant-feedback).
- **One-to-many** (horný vstup má unikátne hodnoty, napr. primárny kľúč) je jednoduchý prípad.
- **Many-to-many** (duplicity na oboch stranách) – SQL Server si musí riadky s rovnakou hodnotou odložiť do pracovnej tabuľky v tempdb (*Worktable* v STATISTICS IO).
- Merge Join funguje pre rovnosť (`=`) a vie aj Left/Right/Full Outer Join, Semi a Anti Semi Join, UNION, INTERSECT…
- *Residual* predikát pri Merge Join = ďalšia podmienka spojenia, ktorá sa testuje až po zhode kľúča.

## Kedy je to v poriadku / kedy problém

| V poriadku | Problém |
|---|---|
| oba vstupy prišli zoradené z indexov (bez Sort) | pred Merge Join je drahý Sort s veľkým memory grantom alebo spillom |
| one-to-many (primárny kľúč na jednej strane) | Many to Many = True a veľa duplicít → Worktable |
| veľké vstupy porovnateľnej veľkosti | jeden vstup malý – Nested Loops so seekom by bol lacnejší |

## Ako si to vyskúšať

```sql
USE PlanLab;
SET STATISTICS IO ON;

-- 1) Oba vstupy zoradené podľa OrderID (klastrované kľúče) → Merge Join bez Sort
SELECT o.OrderID, l.LineNum, l.Qty
FROM dbo.Orders AS o
JOIN dbo.OrderLines AS l ON l.OrderID = o.OrderID
WHERE o.OrderID <= 50000
OPTION (MERGE JOIN);

-- 2) Spojenie cez stĺpec bez vhodného poradia → pred Merge Join pribudne Sort
SELECT c.Name, o.OrderID
FROM dbo.Customers AS c
JOIN dbo.Orders AS o ON o.CustomerID = c.CustomerID
WHERE o.OrderDate >= '20260101'
OPTION (MERGE JOIN);

-- 3) Bez hintu: čo zvolí optimalizátor sám?
SELECT o.OrderID, l.LineNum, l.Qty
FROM dbo.Orders AS o
JOIN dbo.OrderLines AS l ON l.OrderID = o.OrderID
WHERE o.OrderID <= 50000;
```

Spusti s **Include Actual Execution Plan** (Ctrl+M). Pri Merge Join otvor F4 a pozri *Many to Many*, pri Sort *Memory Grant* a prípadné varovanie. Hinty v bodoch 1 a 2 sú len na ukážku.

## Čo s tým

1. Ak pred Merge Join stojí drahý Sort, zváž **index**, ktorý dodá dáta v poradí stĺpcov spojenia – alebo nechaj optimalizátor zvoliť Hash Match (bez hintu).
2. Pri *Many to Many* skontroluj, či spojenie nemá chýbajúcu podmienku (duplicity, ktoré tam nemajú byť).
3. `OPTION (MERGE JOIN)` nepoužívaj v produkčnom kóde, ak nemáš dobrý dôvod – zakáže ostatné typy spojení pre celý dotaz.

## 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)
- [Sort, Top a Top N Sort](script.php?id=75&s=sort-top-a-top-n-sort-zoradovanie-a-pamat)
- [Spill do tempdb](script.php?id=90&s=spill-do-tempdb-sort-a-hash-warning-memory-grant-feedback)
- [Kto spotrebúva tempdb](script.php?id=20&s=kto-spotrebuva-tempdb)

## 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/)
- [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._