==== Často řešené problémy po přechodu na MS SQL 2014 ==== Při přechodu aplikační databáze (DB) z MS SQL Serveru 2012 na verzi 2014 (v ESO9 v5.9) může vlivem nového databázového engine dojít k významnému zpomalení některých datových zdrojů. Tento článek popisuje dosud nalezené problémy a jejich řešení.\\ Obecnější popis diagnostiky výkonových problémů na straně SQL Serveru najdete {{ :techdoc:diagnostika_vykonovych_problemu.pdf | zde}}. === Obecná doporučení === * Od SQL 2014 a zejména od SQL 2016 Microsoft zprovoznil CE(//Cardinality Estimator//), který může způsobovat problémy viz [[https://www.sqlconsulting.com/news1701.htm]]: * Přechod na vyšší verzi SQL Serveru Je potřeba přechod provádět v následujících krocích: * Nejprve vše prověřit v testovacím prostředí s těmito základními kroky: * Držet se doporučení od Microsoftu ([[https://docs.microsoft.com/en-us/sql/database-engine/install-windows/change-the-database-compatibility-mode-and-use-the-query-store?view=sql-server-2017]]). Informace o Query Store např. zde: [[https://www.wug.cz/zaznamy/472-SQL-Server-Bootcamp-2017-Dotazy-pod-kontrolou-SQL-Server-Query-Store]]. * Po změně „Compatibility Level“ (krok 4) na požadovanou hodnotu např.120 – SQL 2014 navíc doporučujeme: * Všechny objekty znovu překompilovat (nejlépe spuštěním verzového skripty + všech doplňků). Výmaz nakešovaných plánů spouštění datových zdrojů lze provést příkazem: DBCC FREEPROCCACHE * Přegenerovat všechny statistiky lze provést příkazem: EXEC sp_updatestats * Přegenerovat všechny indexy lze provést příkazem: EXEC spUdrzbaIndexu * Problematické objekty poté optimalizovat. * Přejít do ostrého prostředí a aplikovat stejný postup, jako v testovacím prostředí. == Návrat k Compatibility Levelu 110 == Protože aktuálně v ESO9 Start a PAM nevyužíváme žádnou syntaxi, která by CL 120 vyžadovala, je nejjednodušším postupem pro optimalizaci aplikace přechod zpět na CL 110. Tím se vytvoří dostatečný prostor pro prověřování a optimalizaci jednotlivých Profi objektů, které pod CL 120 vykazovaly zpomalení. === Cardinality Estimator === Z hlediska výkonu přináší SQL Server 2014 jednu podstatnou změnu a tou je nová verze tzv.//Cardinality Estimatoru//, pomocí kterého SQL Server sestavuje plán na vykonávání SQL dotazu. Všechny předchozí verze SQL Serveru (resp. v7.0 - v2012) používaly //Cardinality Estimator// v70, zatímco SQL Server 2014 používá novou verzi v120. Popis fungování nového //Cardinality Estimatoru// + sadu doporučení najdete v dokumentaci od firmy Microsoft [[https://docs.microsoft.com/en-us/previous-versions/dn673537(v=msdn.10)|zde]]. == Návrat k Cardinality Estimator v70 == Pokud má zákazník ve svých Profi objektech některý, jež vyžaduje CL 120 (a tedy návrat k CL 110 již není možný), lze se vrátit zpět i s verzí //Cardinality Estimatoru//: * Na MS SQL Serveru 2014 lze nastavit //Cardinality Estimator// pouze na úrovni celého serveru příkazem: DBCC TRACEON (9481,-1) * Od MS SQL Serveru 2016 lze nastavit //Cardinality Estimator// na úrovni jednotlivých databází příkazem: ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = ON; === Řešené problémy z praxe === == Nové indexy == Nejsnáze řešitelným problémem jsou neexistující indexy. Následující pohled nad stazkami (zjednodušeno) trval na CL=110 zhruba 1 sec:\\ CREATE VIEW [dbo].[QSTAZKA] as SELECT HDOK.* , UCET_OBD, TYPDOK.TYP_DOK, /* tabulka HDOKADD */ HDOKADD.IDHDOKADD AS BTHDOKADD, HDOKADD.IDHDOK AS RIDHDOK_BTHDOKADD, ... SUBJEKT.KOD_SUBJEKTU, SUBJEKT.SUBJ_NAZEV, CASE WHEN VLSTAVHDOK = 10 THEN 7 ELSE IDHDOK_VZOR END AS MF_IDHDOKVZOR, 'spPostKopie_STAZKA' as MF_EXECHDOK, 'spPostKopie_STAZKA_SDOK' AS MF_EXECSDOK, 0 AS MF_NEANOHIS, (SELECT MAX(CIS_DOK) FROM hdok HIS WITH(NOLOCK) WHERE HIS.V_SYM_ZALOHY =HDOK.V_SYM_ZALOHY AND HIS.IDHDOK > HDOK.idhdok) AS MF_CIS_DOK_NEW, CONCAT(KOD_CENIK,'-',NAZEV_CENIK) AS CENIK FROM HDOK with(NoLock) LEFT JOIN ... Po přechodu na CL=120 se zvedla doba vyhodnocení pohledu nad stejnými daty zhruba na 37 sec. Rozborem //Execution Planu// se zjistilo, že vnořený select nemá k dispozici správný index a provádí //Index Scan// nad velkým počtem řádků: (SELECT MAX(CIS_DOK) FROM hdok HIS WITH(NOLOCK) WHERE HIS.V_SYM_ZALOHY =HDOK.V_SYM_ZALOHY AND HIS.IDHDOK > HDOK.idhdok) AS MF_CIS_DOK_NEW Po doplnění indexu se dotaz zrychlil na původní cca 1 sec: CREATE NONCLUSTERED INDEX HDOK_V_SYM_ZALOHY_CIS_DOK ON dbo.HDOK (V_SYM_ZALOHY,CIS_DOK)