> [!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: **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._
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.