Качеството на плана за изпълнение е силно зависимо от точността на приблизителния брой редове, изведени от всеки оператор на плана. Ако прогнозният брой редове е значително изкривен от действителния брой редове, това може да окаже значително влияние върху качеството на плана за изпълнение на заявката. Лошото качество на плана може да е причина за прекомерно I/O, надуване на процесора, натиск върху паметта, намалена пропускателна способност и намален общ паралел.
Под „качество на плана“ – говоря за това, че SQL Server генерира план за изпълнение, който води до избор на физически оператор, който отразява текущото състояние на данните. Като се вземат такива решения въз основа на точни данни, има по-голям шанс заявката да се изпълни правилно. Стойностите за оценка на кардиналитета се използват като входни данни за операторски разходи и когато стойностите са твърде далеч от реалността, може да се изрази отрицателното въздействие върху плана за изпълнение. Тези оценки се подават на различните модели на разходите, свързани със самата заявка, и лошите оценки на редове могат да повлияят на различни решения, включително избор на индекс, операции за търсене и сканиране, паралелно срещу серийно изпълнение, избор на алгоритъм за присъединяване, вътрешно срещу външно физическо свързване избор (напр. компилация срещу проба), генериране на буфера, търсене на отметки спрямо пълен клъстерен или хеп достъп до таблица, избор на поток или хеш агрегат и дали модификацията на данни използва широк или тесен план.
Като пример, да приемем, че имате следния SELECT
заявка (използвайки базата данни за кредит):
SELECT m.member_no, m.lastname, p.payment_no, p.payment_dt, p.payment_amt FROM dbo.member AS m INNER JOIN dbo.payment AS p ON m.member_no = p.member_no;
Въз основа на логиката на заявката, следната форма на плана това, което бихте очаквали да видите?
А какво ще кажете за този алтернативен план, където вместо вложен цикъл имаме съвпадение на хеш?
„Правилният“ отговор зависи от няколко други фактора – но един основен фактор е броят на редовете във всяка от таблиците. В някои случаи един алгоритъм за физическо свързване е по-подходящ от другия – и ако първоначалните предположения за оценка на мощността не са правилни, заявката ви може да използва неоптимален подход.
Идентифициране Проблемите с оценката на кардиналността са сравнително прости. Ако имате действителен план за изпълнение, можете да сравните прогнозните спрямо действителните стойности на броя на редовете за операторите и да потърсите изкривявания. SQL Sentry Plan Explorer опростява тази задача, като ви позволява да видите действителните спрямо прогнозните редове за всички оператори в един раздел на дървото на плановете, вместо да трябва да задържите курсора на мишката върху отделните оператори в графичния план:
Сега изкривяванията не винаги водят до планове с лошо качество, но ако имате проблеми с производителността на заявка и виждате такива изкривявания в плана, това е една област, която си заслужава допълнително проучване.
Идентифицирането на проблемите с оценката на мощността е сравнително лесно, но решението често не е. Има редица основни причини, поради които могат да възникнат проблеми с оценката на кардиналността и ще разгледам десет от по-често срещаните причини в тази публикация.
Липсващи или остарели статистически данни
От всички причини за проблеми с оценката на кардиналността, това е тази, на която се надявате да видите, тъй като често е най-лесно да се адресира. В този сценарий статистическите ви данни или липсват, или са остарели. Възможно е да имате опциите на базата данни за автоматично създаване на статистически данни и деактивирани актуализации, да активирате „без повторно изчисление“ за конкретни статистически данни или да имате достатъчно големи таблици, така че автоматичните ви актуализации на статистиката просто да не се случват достатъчно често.
Проблеми с извадката
Може да се окаже, че прецизността на статистическата хистограма е недостатъчна – например, ако имате много голяма таблица със значителни и/или чести изкривявания на данните. Може да се наложи да промените извадката си от стандартната или ако дори това не помогне – проучете с помощта на отделни таблици, филтрирани статистически данни или филтрирани индекси.
Корелации на скрити колони
Оптимизаторът на заявки приема, че колоните в една и съща таблица са независими. Например, ако имате колона за град и щат, може интуитивно да знаем, че тези две колони са свързани, но SQL Server не разбира това, освен ако не му помогнем със свързан индекс с няколко колони или с ръчно създадени мулти-колони статистика на колоните. Без да помагате на оптимизатора с корелацията, селективността на вашите предикати може да бъде преувеличена.
По-долу е даден пример за два корелирани предиката:
SELECT lastname, firstname FROM dbo.member WHERE city = 'Minneapolis' AND state_prov - 'MN';
Случайно знам, че 10% от нашите 10 000 ред member
таблица отговаря на условията за тази комбинация, но оптимизаторът на заявки предполага, че това е 1% от 10 000 реда:
Сега контрастирайте това с подходящата оценка, която виждам след добавяне на статистически данни за няколко колони:
Сравнения на колони в таблици
Проблеми с оценката на кардиналността могат да възникнат при сравняване на колони в една и съща таблица. Това е известен проблем. Ако трябва да го направите, можете да подобрите оценките за мощността на сравненията на колони, като вместо това използвате изчислени колони или като пренапишете заявката, за да използвате самообединявания или общи изрази на таблици.
Използване на променлива в таблица
Използвате ли много променливи в таблицата? Променливите в таблицата показват оценка на кардиналността от "1" - което само за малък брой редове може да не е проблем, но за големи или променливи набори от резултати може значително да повлияе на качеството на плана на заявката. По-долу е екранна снимка на оценката на оператора за 1 ред спрямо действителните 1 600 000 реда от @charge
променлива в таблицата:
Ако това е основната ви причина, ще бъдете добре посъветвани да проучите алтернативи като временни таблици или постоянни таблици, където е възможно.
Скаларни и MSTV UDF
Подобно на променливите в таблицата, таблично-стойностните и скаларните функции с множество изрази са черна кутия от гледна точка на оценката на мощността. Ако се сблъскате с проблеми с качеството на плана поради тях, помислете за функциите на вградена таблица като алтернатива – или дори да изтеглите изцяло препратката към функцията и просто да препратите директно към обекти.
По-долу е показан прогнозен спрямо действителен план, когато се използва функция с таблично стойности с множество изрази:
Проблеми с типа данни
Проблеми с имплицитните типове данни във връзка с условията за търсене и присъединяване могат да причинят проблеми с оценката на кардиналността. Те също така могат тайно да изядат ресурсите на ниво сървър (CPU, I/O, памет), така че е важно да се обръщаме към тях, когато е възможно.
Сложни предикати
Вероятно сте виждали този модел преди – заявка с WHERE
клауза, която има всяка препратка към колона на таблицата, обвита в различни функции, операции за конкатенация, математически операции и др. И въпреки че не всички обвивания на функции изключват правилни оценки за кардиналност (като за LOWER
, UPPER
и GETDATE
) има много начини да погребете предиката си до степен, че оптимизаторът на заявки вече не може да прави точни оценки.
Сложност на заявката
Подобно на погребаните предикати, вашите заявки са изключително сложни? Осъзнавам, че „комплекс“ е субективен термин и вашата оценка може да варира, но повечето могат да се съгласят, че вложените изгледи в изгледи в изгледи, които препращат припокриващи се таблици, вероятно ще бъдат неоптимални – особено когато се съчетават с 10+ свързвания на таблици, препратки към функции и заровени предикати. Въпреки че оптимизаторът на заявки върши възхитителна работа, това не е магия и ако имате значителни изкривявания, сложността на заявката (заявки с швейцарски нож) със сигурност може да направи почти невъзможно извличането на точни оценки на редовете за операторите.
Разпределени заявки
Използвате ли разпределени заявки със свързани сървъри и виждате значителни проблеми с оценката на кардиналността? Ако е така, не забравяйте да проверите разрешенията, свързани с принципала на свързания сървър, който се използва за достъп до данните. Без минималния db_ddladmin
фиксирана роля на база данни за акаунта на свързания сървър, тази липса на видимост за отдалечени статистически данни поради недостатъчни разрешения може да е източникът на проблемите ви с оценката на кардиналността.
И има и други...
Има и други причини, поради които оценките за кардиналите могат да бъдат изкривени, но вярвам, че разгледах най-често срещаните. Ключовият момент е да се обърне внимание на изкривяванията във връзка с известни, лошо работещи заявки. Не приемайте, че планът е генериран въз основа на точни условия за преброяване на редове. Ако тези числа са изкривени, първо трябва да опитате да отстраните проблема.