Úvod
Dokumentace k produktu SQL Server je trochu lehká na téma cíle řádků . Hlavní oficiální odkazy jsou v:
- Tipy (Transact-SQL) – Dotaz (
FAST
aDISABLE_OPTIMIZER_ROWGOAL
rady) - DBCC TRACEON – příznaky trasování (Transact-SQL) (příznak trasování 4138)
- Spuštění dotazu může trvat dlouho, pokud optimalizátor dotazů používá operátor Top (KB 2667211)
Když lidé požádají o více informací, než je tam uvedeno, obvykle jim odkážu jednu nebo více z následujících:
- Řádkové cíle v akci od týmu SQL Server Query Optimization Team
- Opětovně přezkoumány cíle řádků – RYCHLÉ rady také od týmu SQL Server Query Optimization Team
- Row Gone Gone Rogue od Barta Duncana
- Inside the Optimizer:Row Goals In Hloubka mnou
- Tip pro ladění SSIS, který od Roba Farleyho každému chybí
Stručně shrnuto:Funkce cíle řádku umožňuje optimalizátoru generovat plán provádění (nebo část(i) plánu provádění) s cílem rychle vrátit určitý počet řádků. To je v kontrastu s normálním chováním (bez cíle řádku), jehož cílem je najít plán optimalizovaný pro kompletní sadu potenciálních výsledků.
Strategie cíle řádku obecně znamená upřednostňování neblokujících navigačních operací (například spojení vnořených smyček, hledání indexů a vyhledávání) před blokováním operací založených na množinách, jako je třídění a hašování. To může být užitečné, kdykoli může klient těžit z rychlého spuštění a stabilního proudu řádků (s možná delší celkovou dobou provádění – viz příspěvek Roba Farleyho výše). Existují také zjevnější a tradiční použití, např. při prezentaci výsledků po stránce.
S plánem cílů řady je přirozeně spojen prvek rizika. Pokud se vše odehrává obecně tak, jak optimalizátor očekává (vzhledem k dostupným informacím a použitým předpokladům modelování), plán provádění začne streamovat požadovaný počet řádků rychleji a efektivněji, než by tomu bylo bez cíle řádku.
Bohužel, když se pokazí strategie cíle, může to být výkonnostní katastrofa (viz příspěvek Barta Duncana). To se může stát například tehdy, když má optimalizátor neúplné informace, narazí na nepříznivou distribuci dat nebo udělá nebezpečný předpoklad. V každém případě je příčinou slabého výkonu téměř vždy to, že při provádění je potřeba zpracovat mnohem více řádků, než optimalizátor očekával.
Může být velmi užitečné identifikovat oblasti plánu realizace ovlivněné cílem řádku, protože nám to pomáhá pochopit proč optimalizátor provedl volby, které udělal. To je zvláště důležité, když logika cíle řádku produkuje nepříznivý výsledek. Bez pochopení role, kterou hraje cíl řádku, by to mohlo vypadat, jako by optimalizátor jednoduše podcenil počet řádků, což vedlo lidi k tomu, aby hledali hlavní příčinu na nesprávných místech (např. ve statistikách).
Nastavení cílů řádku
Je mnohem snazší hledat efekty na cíl řádku, pokud člověk ví, jaké druhy věcí mohou způsobit, že se na prvním místě stanoví cíl řádku. Oficiální dokumentace často hovoří o tom, že cíle řádku jsou spojeny s klíčovými slovy TOP
, FAST
, IN
a EXISTS
. To může čtenáři zanechat neúplné nebo zavádějící porozumění, takže stojí za to věnovat chvíli objasnění některých aspektů.
Hned na začátku bych chtěl zdůraznit, že používám konkrétní klíčová slova T-SQL v dotazunezaručuje, že bude nastaven cíl řádku . Oficiální dokumentace zmiňuje určitá klíčová slova, která lidem pomáhají identifikovat běžné scénáře, kde cíle řádku mohou být představen, aniž byste se zabývali příliš mnoha technickými detaily.
Druhým obecným bodem, který je třeba mít na paměti, je, žecíl řádku je nastaven pouze v případě, že by byl cíl nižší než běžný odhad . Koneckonců, nemá moc smysl generovat fragment plánu optimalizovaný pro 100 řádků, pokud se očekává, že celá věc stejně vytvoří pouze 50 řádků. Aby bylo jasno, tento bod vždy platí pro všechny způsoby, jak lze nastavit cíl řádku. Pokud očekáváte cíl řádku, ale žádný nevidíte, je to pravděpodobná příčina.
Na závěr, pro preambuli, poznamenejte, že cíle řádků jsou věcí optimalizace založenou na nákladech; cíl řádku ovlivňuje volby optimalizátoru, takže pokud není třeba provést žádné volby (tj. triviální plán), nemá to žádný účinek na cíl řádku.
Podívejme se nyní na věci, které mohou stanovit cíl řádku:
RYCHLE a TOP
Pomocí FAST
query hint je spolehlivý způsob, jak nastavit cíl řádku v rootu prováděcího plánu (s výhradou obecných výjimek uvedených výše). A SET ROWCOUNT n
příkaz také nastavuje podobný cíl řádku nejvyšší úrovně (když n
není samozřejmě nula) pro příkazy, kterých se týká.
Psaní TOP
klauzule v dotazu také velmi často vede k cíli řádku. Dokud dokončený plán realizace obsahuje fyzického top operátora, je pravděpodobné, že alespoň část plánu pod top operátorem byla ovlivněna cílem řádku (opět platí všeobecné smluvní podmínky).
Všimněte si, že top operátory zavedené optimalizátorem dotazů (bez dotazu zadaného TOP
klauzule) může také nastavit cíl řádku. To je důležité, protože k tomu může dojít nejrůznějšími způsoby, například při filtrování podle čísla jednoduchého řádku, jak ukazuje následující dotaz AdventureWorks:
SELECT THN.RowNum, THN.TransactionID FROM ( SELECT TH.TransactionID, RowNum = ROW_NUMBER() OVER ( ORDER BY TH.TransactionID ASC) FROM Production.TransactionHistory AS TH WHERE TH.ProductID = 400 ) AS THN WHERE THN.RowNum >= 10 AND THN.RowNum < 20 ORDER BY THN.RowNum ASC;
Plán provádění pro tento dotaz zahrnuje operátor Top přidaný optimalizátorem (k omezení počtu zpracovaných řádků na 20):