> [!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  Rovnaký dotaz (query_id) má v **Query Store** viac plánov (plan_id) s výrazne iným trvaním. V SSMS: databáza → *Query Store* → **Regressed Queries** alebo **Tracked Queries** – graf s bodkami podľa plánov a tlačidlá *Force Plan* / *Unforce Plan* / *Compare Plans*. ## Čo to znamená **Plan regression** = dotaz dostal nový plán a ten je horší. Príčiny: rekompilácia s inou hodnotou parametra ([parameter sniffing](script.php?id=87&s=parameter-sniffing-jeden-plan-pre-rozne-hodnoty-psp-2022-oppo-2025)), update štatistík, zmena dát, nový index alebo jeho zmazanie, zmena compat levelu / CE ([Cardinality estimator](script.php?id=85&s=cardinality-estimator-ce-70-vs-120-a-compat-level)), upgrade servera. Query Store si pamätá plány aj ich výkon v čase, takže vieš ukázať „kedy a čím“ – a dobrý plán **vynútiť**. ### Do hĺbky - **Vynútenie plánu** – `sp_query_store_force_plan @query_id, @plan_id` (alebo tlačidlo v SSMS). Optimalizátor pri kompilácii použije vynútený tvar. Ak sa to nepodarí (zmazaný index, zmena schémy), dotaz beží s novým plánom a Query Store zapíše `force_failure_count` / `last_force_failure_reason_desc`. - **Automatic plan correction** (2017+, `AUTOMATIC_TUNING (FORCE_LAST_GOOD_PLAN = ON)`) – SQL Server sám vynúti posledný dobrý plán pri zistenej regresii; odporúčania v `sys.dm_db_tuning_recommendations`. - **Query Store hints** (2022+) – `sys.sp_query_store_set_hints` pridá hint (napr. RECOMPILE, MAXDOP, compat level) k dotazu bez zmeny kódu aplikácie. - **Optimized plan forcing** (2022+) – vynútené plány sa kompilujú rýchlejšie (uložený postup optimalizácie). - Query Store je pre nové databázy zapnutý predvolene od SQL Server 2022; v starších verziách ho treba zapnúť. Stav ukáže recept [Query Store – konfigurácia a stav](script.php?id=46&s=query-store-konfiguracia-a-stav). ## Kedy je to v poriadku / kedy problém | V poriadku | Problém | |---|---| | viac plánov s podobným výkonom | jeden plán rádovo pomalší a často používaný | | vynútený plán ako dočasná oprava s poznámkou | stovky vynútených plánov, ktoré nikto neeviduje | | | vynútenie zlyháva (force_failure_count > 0) | ## Ako si to vyskúšať ```sql USE PlanLab; ALTER DATABASE PlanLab SET QUERY_STORE = ON (OPERATION_MODE = READ_WRITE, QUERY_CAPTURE_MODE = ALL); ALTER DATABASE PlanLab SET QUERY_STORE CLEAR; GO CREATE OR ALTER PROCEDURE dbo.Lab_Regress @CustomerID int AS SELECT OrderID, Amount, Note FROM dbo.Orders WHERE CustomerID = @CustomerID; GO EXEC dbo.Lab_Regress 42; EXEC dbo.Lab_Regress 42; EXEC dbo.Lab_Regress 1; -- plán A (seek + lookup) EXEC sp_recompile N'dbo.Lab_Regress'; EXEC dbo.Lab_Regress 1; EXEC dbo.Lab_Regress 42; EXEC dbo.Lab_Regress 42; -- plán B (sken) GO -- plány dotazu a ich výkon SELECT q.query_id, p.plan_id, rs.count_executions, rs.avg_duration / 1000.0 AS avg_ms, rs.avg_logical_io_reads FROM sys.query_store_query AS q JOIN sys.query_store_plan AS p ON p.query_id = q.query_id JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = p.plan_id WHERE q.object_id = OBJECT_ID(N'dbo.Lab_Regress'); -- vynútenie (doplň čísla z výsledku) a zrušenie -- EXEC sys.sp_query_store_force_plan @query_id = 1, @plan_id = 1; -- EXEC sys.sp_query_store_unforce_plan @query_id = 1, @plan_id = 1; GO DROP PROCEDURE dbo.Lab_Regress; -- ALTER DATABASE PlanLab SET QUERY_STORE = OFF; ``` Otvor v SSMS *Query Store* → *Tracked Queries*, zadaj query_id a porovnaj plány (*Compare Plans*). Všetko sa deje len v PlanLab. ## Čo s tým 1. Zisti, **ktorý plán bol dobrý** a **čo sa zmenilo** (štatistiky, parameter, index, compat level). 2. Ako rýchlu opravu vynúť dobrý plán (zaznač si to). Dlhodobo odstráň príčinu – vynútený plán môže časom prestať byť dobrý. 3. Pravidelne kontroluj [Query Store – regresie](script.php?id=26&s=query-store-regresie-24-h-vs-predoslych-24-h) a vynútené plány (`is_forced_plan = 1`, zlyhania vynútenia). 4. Pred upgrade / zmenou compat levelu zbieraj baseline v Query Store. ## Súvisiace - [Query Store – regresie](script.php?id=26&s=query-store-regresie-24-h-vs-predoslych-24-h) - [Query Store – konfigurácia a stav](script.php?id=46&s=query-store-konfiguracia-a-stav) - [Query Store – top dotazy podľa CPU](script.php?id=25&s=query-store-top-dotazy-podla-cpu) - [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) - [Ako získať exekučný plán](script.php?id=66&s=ako-ziskat-exekucny-plan-ssms-plan-cache-query-store-extended-events) ## Zdroje - [Microsoft Learn – Monitor performance by using the Query Store](https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store) - [Microsoft Learn – sp_query_store_force_plan](https://learn.microsoft.com/sql/relational-databases/system-stored-procedures/sp-query-store-force-plan-transact-sql) - [Microsoft Learn – Query Store hints](https://learn.microsoft.com/sql/relational-databases/performance/query-store-hints) - [Microsoft Learn – Intelligent query processing](https://learn.microsoft.com/sql/relational-databases/performance/intelligent-query-processing) _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._
Plan regression – nový horší plán a vynútenie cez Query Store
Keď dotaz zrazu spomalí kvôli novému plánu: Query Store a jeho plány v čase, Regressed Queries, vynútenie plánu (sp_query_store_force_plan), automatic plan correction a Query Store hints (2022+).