Nová vlastnost „Aktuální čtení řádků“ v plánech provádění (která se v SQL Server Management Studio zobrazuje jako „Počet přečtených řádků“) byla vítaným doplňkem k ladění výkonu. Je to jako mít novou superschopnost, být schopen rozlišit význam predikátu hledání vs. reziduálního predikátu v rámci operátoru hledání. Líbí se mi to, protože to může být pro dotazování opravdu důležité.
Podívejme se na dva dotazy, které spouštím proti AdventureWorks2012. Jsou velmi jednoduché – jeden uvádí lidi jménem John S a druhý uvádí lidi jménem J Smith. Jako všechny dobré telefonní seznamy máme index Příjmení, Jméno.
select FirstName, LastName from Person.Person where LastName like 'S%' and FirstName = 'John'; select FirstName, LastName from Person.Person where LastName = 'Smith' and FirstName like 'J%';
V případě, že jste zvědaví, dostávám 2 řádky zpět od prvního a 14 řádků zpět od druhého. Mě vlastně ani tak nezajímají výsledky, ale realizační plány.
Podívejme se, co se děje. Otevřel jsem starší kopii SQL Sentry Plan Explorer a otevřel své plány vedle sebe. Mimochodem – spustil jsem oba dotazy společně, takže oba plány byly ve stejném souboru .sqlplan. Ale mohl bych otevřít stejný soubor dvakrát v PE a šťastně je posadit vedle sebe do skupin karet.
Skvělý. Vypadají stejně! Vidím, že hledání vlevo vytváří dva řádky místo čtrnácti – to je samozřejmě lepší dotaz.
Ale s větším oknem bych viděl více informací a je štěstí, že jsem tyto dva dotazy spustil ve stejné dávce.
Můžete vidět, že druhý dotaz, který produkoval 14 řádků místo 2 řádků, podle odhadů přebírá 80 % nákladů! Pokud bych spouštěl dotazy samostatně, každý by mi zobrazoval 100 %.
Nyní porovnejme s nejnovější verzí Plan Explorer.
Věc, která mi okamžitě naskočí, je varování. Podívejme se trochu blíž.
Varování říká:„Operace způsobila zbytkové IO. Skutečný počet přečtených řádků byl 2 130, ale počet vrácených řádků byl 2.“ Jistě, výše vidíme „Aktuální řádky přečteny“ s hodnotou 2 130 a Skutečné řádky na 2.
Páni! Abychom našli tyto řádky, museli jsme se podívat přes 2 130?
Vidíte, způsob, jakým Seek běží, je začít přemýšlením o predikátu Seek. To je ten, který pěkně využívá index a který ve skutečnosti způsobuje, že operace je Seek. Bez predikátu hledání se operace stane skenováním. Nyní, pokud je zaručeno, že tento predikát vyhledávání bude mít nejvýše jeden řádek (například když má operátor rovnosti na jedinečném indexu), pak máme vyhledávání Singleton. Jinak máme Range Scan a tento rozsah může mít předponu, začátek a konec (ale nemusí nutně oba začátek a konec). To definuje řádky v tabulce, které nás zajímají pro hledání.
Ale ‚zájem o‘ nemusí nutně znamenat ‚vrácený‘, protože můžeme mít více práce. Tato práce je popsána v druhém predikátu, který je často známý jako zbytkový predikát.
Nyní, když Residual Preddicate ve skutečnosti dělá většinu práce. Určitě je tady – filtruje věci z 2 130 řádků na pouhé 2.
Range Scan začíná v indexu u „John S“. Víme, že pokud existuje „John S“, musí to být první řada, která může celou věc uspokojit. "Ian S" nemůže. V tomto bodě tedy můžeme vyhledávat v indexu, abychom zahájili náš Range Scan. Pokud se podíváme na plán XML, můžeme to vidět explicitně.
Všimněte si, že nemáme předponu. To platí, když máte v prvním sloupci v indexu rovnost. Máme jen StartRange a EndRange. Začátek rozsahu je „Větší než nebo stejný“ (GE) ScanType s hodnotou „S, John“ (odkazy ve sloupcích mimo obrazovku jsou Příjmení, Jméno) a Konec rozsahu je „Menší než“ ( LT) hodnotu T. Když skenování narazí na T, je hotovo. Není co dělat. Seek nyní dokončil skenování rozsahu. A v tomto případě vrátí 2 130 řádků!
Kromě toho, že ve skutečnosti nevrací 2 130 řádků, pouze přečte 2 130 řádků. Jména jako Barry Sai a Ken Sánchez se přečtou, ale vrátí se pouze jména, která vyhovují další kontrole – zbytkový predikát, který zajistí, že jméno je John.
Položka Skutečné čtení řádků ve vlastnostech operátoru Index Seek nám ukazuje tuto hodnotu 2 130. A i když je to vidět v dřívějších verzích Plan Exploreru, nedostáváme na to varování. To je relativně nové.
Náš druhý dotaz (hledá J Smith) je mnohem hezčí a existuje důvod, proč se odhaduje, že bude více než 4krát levnější.
Zde známe příjmení přesně (Smith) a rozsah skenování je na jméno (J%).
Zde přichází na řadu předpona.
Vidíme, že naše předpona je operátor rovnosti (=, ScanType=”EQ”) a že Příjmení musí být Smith. Ještě jsme ani neuvažovali o začátku nebo konci rozsahu, ale předpona nám říká, že rozsah je zahrnut v části indexu, kde je příjmení Smith. Nyní můžeme najít řádky>=J a
Stále zde existuje reziduální predikát, ale pouze se ujistěte, že je skutečně testováno „LIKE J %“. I když se nám zdá intuitivní, že „LIKE J %“ je přesně ekvivalentní „>=J a
Před aktualizací Service Pack 3 SQL Server 2012 jsme tuto vlastnost neměli, a abychom získali pocit, jaký je rozdíl mezi skutečnými přečtenými řádky a skutečnými řádky, museli bychom použít příznak trasování 9130. Zde jsou tyto dva plány se zapnutým TF:
Můžete vidět, že tentokrát není žádné varování, protože operátor Seek vrací všech 2130 řádků. Domnívám se, že pokud používáte verzi SQL Server, která podporuje čtení aktuálních řádků, měli byste ve svých šetřeních přestat používat příznak trasování 9130 a místo toho se začít dívat na varování v Průzkumníku plánů. Ale především pochopte, jak vaši operátoři dělají své věci, protože pak budete schopni interpretovat, zda jste s plánem spokojeni, nebo zda je třeba jednat.
V dalším příspěvku vám ukážu situaci, kdy možná dáváte přednost tomu, aby bylo Skutečné přečtené řádky vyšší než Skutečné řádky.
@rob_farley