Едно от най-трудните предизвикателства в SQL Server е отстраняването на проблеми с чувствителността на параметрите или оценката на мощността, които причиняват влошаване на производителността на работното натоварване. Като цяло ще трябва да имате действителния план за изпълнение от оператора, за да можете да определите причината за влошаване на производителността. В SQL Server 2012 разширеното събитие query_post_execution_showplan предоставя възможност за улавяне на действителния план за изпълнение на изрази. Въпреки това, колкото и полезно да изглежда това, това събитие не е нещо, което може да се използва без значително въздействие върху производителността върху натоварването, изпълнявано на сървъра.
В моята статия Измерване на „режимите на наблюдателя“ на SQL Trace спрямо разширени събития, показах сравнение на въздействието върху производителността на SQL Trace спрямо идентична конфигурация, използвайки разширени събития в SQL Server 2012. По времето, когато първоначално направих тестването за тази статия Освен това направих много тестове на събитието query_post_execution_showplan в SQL Server 2012. Това събитие беше въведено за първи път в SQL Server 2012 CTP1, когато много от събитията за проследяване бяха пренесени към разширени събития, за да се осигури паритет със SQL Trace. По това време събитието имаше само подмножество от колоните, които бяха включени в окончателния RTM на SQL Server 2012.
По време на CTP1 изпратих елемент за свързване с искане да се създаде действие, което да позволи събирането на действителния план за изпълнение със събития в SQL Server 2012. Целта беше да мога да използвам събитията module_end или sql_statement_completed, за да идентифицирам кога е изпълнението на процедура или изявлението надвишава нормалната си продължителност. Например, в сценария на чувствителност на параметрите, където се генерира по-малко идеален план за нормалните стойности на параметрите, събитието може да се използва за събиране на действителния план за изпълнение за този израз чрез действие. В отговор екипът на SQL Server добави колоните duration и cpu_time към събитието query_post_execution_showplan, за да позволи дефинициите на предикатите да събират това събитие само за тези сценарии.
За съжаление това няма същите ползи, които една реализация като действие би имала за производителността. В останалата част от тази публикация ще обясня защо.
Влияние върху производителността
По времето, когато направих тестването за предишната си статия, тествах и режийните разходи, свързани със събитието query_post_execution_showplan, главно защото наистина се интересувах да го използвам в няколко клиентски производствени системи и преди да го направя, трябваше да разбера какво вид влияние, което събитието би имало върху работното им натоварване. Бях наистина разтревожен от резултатите, които получих от първоначалните си тестове, и след като накарах Аарон Бертран да валидира резултатите ми с помощта на вътрешния тестов ремък на SQL Sentry, подадох друг елемент на Connect, съобщаващ за проблемите с производителността, който впоследствие беше затворен като „По проект“ .
За тестване на въздействието върху производителността е използвано точно същото работно натоварване и конфигурация за разпределено възпроизвеждане от статията Измерване на „Наблюдателски разходи“ на SQL Trace срещу разширени събития. Единствената разлика за резултатите от теста, показани в тази статия, е, че за средата на VM беше използвана по-нова, по-мощна хост система. Използваните виртуални машини бяха абсолютно същите, без промени в конфигурацията им и те просто бяха копирани в новата система, поради което основното работно натоварване успя да извърши повторното възпроизвеждане по-бързо с по-висока средна стойност на пакетни заявки/сек. Основните резултати бяха заснети с помощта на стандартна инсталация на SQL Server 2012, като на сървъра се изпълняваше само сесията за събитие system_health по подразбиране.
За сравнение на въздействието върху производителността на query_post_execution_showplan
събитие, беше използвана следната дефиниция на сесия на събитие.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan( WHERE ([duration]=(5000000))); GO
Тази сесия всъщност не събира данните за събитието, използвайки цел и използва предикат за продължителността за продължителността на събитието, равна на 5000000 микросекунди или продължителност от пет секунди. За натоварването с повторение, изпълнението на нито един израз не е с продължителност точно пет секунди, така че събитието query_post_execution_showplan никога не се задейства в сървъра и всяко влошаване на производителността е стриктно резултат от събирането на данни за събитието и след това оценката на предиката. Резултатите от тестовете са показани в Таблица 1 и диаграми в Графика 2.
Таблица 1 – query_post_execution събитие режийни
Диаграма 2 – query_post_execution събитие режийни
За този кръг от тестове производителността на работното натоварване се влошава с приблизително 30% чрез просто активиране на това събитие в сесия на събитие, въпреки че няма да се задейства за никое от събитията, които се възпроизвеждат на сървъра. Цялостното влошаване ще зависи от действителното работно натоварване на сървъра и е важно да се отбележи, че тази серия от тестове отразява повече от най-лошия сценарий, тъй като разпределеното повторение се изпълняваше в режим на стрес и използването на процесора на SQL Server беше фиксирано средно 94% по време на тестовете.
Разбиране на въздействието върху производителността
Причината, поради която това събитие налага толкова значителни разходи върху производителността, може да се обясни от жизнения цикъл на събитието в Разширени събития. Когато по време на изпълнение се срещне критична точка в кода на SQL Server, свързан със събитие, кодът извършва много бърза булева проверка, за да определи дали събитието е активирано във всяка активна сесия за събитие на сървъра. Ако събитието е активирано за активна сесия на събитие, всички колони с данни, свързани със събитието, се събират, включително всички колони с възможност за персонализиране, които са били включени. В този момент събитието оценява всички предикати за активните сесии на събития, които събират събитието, за да определи дали събитието действително ще се задейства напълно.
За събитието query_post_exection_showplan цялото въздействие върху производителността е от режийните разходи, свързани със събирането на данни. Дори в случай, когато има предикат за продължителност, равна на пет секунди, само чрез включване на събитието в сесия на събитие, той трябва да събере Showplan XML за всеки израз, който се изпълнява на сървъра, само за да може да оцени предиката и след това да се определи, че събитието няма да се задейства. Поради тази причина събитието query_post_execution_showplan трябва да се избягва за производствени натоварвания. За натоварването на тестовото повторно възпроизвеждане събитието трябваше да бъде оценено приблизително 440 000 пъти, въпреки че всъщност не се задейства за сесията на натоварване и събитие, която се тества, тъй като нито едно от събитията за възпроизвеждане няма продължителност точно пет секунди. Информацията за броя на събитията беше събрана чрез добавяне на целта event_counter към сесията на събитието и премахване на предиката за продължителност и след това повторно тестване на натоварването с повторение със следната дефиниция на сесията.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan ADD TARGET package0.event_counter; GO
Сравнение с бързо стрелящи събития
За да предоставим референтна рамка за това въздействие върху производителността, можем да разгледаме режийните разходи за включване на набор от често изпълнявани събития в сървъра и извършване на същото натоварване за възпроизвеждане. Две от най-често изпълняваните събития в SQL Server са събитията lock_acquired и lock_released. За да се сравнят режийните разходи на тези две събития, може да се използва следната сесия за събития, която събира събитията без предикат, така че всяко изпълнение да се събира и отчита колко често се задействат с помощта на целта event_counter.
CREATE EVENT SESSION [locking Overhead] ON SERVER ADD EVENT sqlserver.lock_acquired, ADD EVENT sqlserver.lock_released ADD TARGET package0.event_counter; GO
За нашето натоварване с повторения тези две събития се задействат приблизително 111 180 000 пъти. Разходите, свързани със събирането на тези събития, могат да се видят в Таблица 3 и Графика 4.
Таблица 3 – Заключване на режийно сравнение
Графика 4 – Сравнение на заключващи събития
Както можете да видите от данните, ефектът на производителността на тези събития е значително по-нисък, отколкото за query_post_execution_showplan, въпреки че дефиницията на сесията на заключващото събитие е конфигурирана да позволи на всички събития да се задействат на сървъра, общите разходи бяха под 1% като цяло . Имайте предвид, че сесията на заключващото събитие оценява еквивалента на 500 пъти повече събития и в този случай всички събития действително трябваше да се задействат за сесията на събитието, където събитието query_post_execution_showplan всъщност не трябваше да се задейства, след като беше оценено.
Резюме
Докато събитието query_post_execution_showplan предоставя възможност за събиране на действителния план на заявка за изпълнение, въздействието на събирането на данни само за оценка на събитието го прави нещо, което не е жизнеспособно за производствена употреба. Като минимум, режийните разходи трябва да бъдат взети предвид, преди да използвате това събитие срещу производствено натоварване. Дори описанието на събитието, предоставено от Microsoft, потвърждава, че събитието може да има значително въздействие върху производителността (моето подчертаване):
Възниква след изпълнение на SQL оператор. Това събитие връща XML представяне на действителния план за заявка. Използването на това събитие може да доведе до значителни разходи за производителност, така че трябва да се използва само при отстраняване на неизправности или наблюдение на конкретни проблеми за кратки периоди от време.Описанието на събитието може да бъде намерено в колоната за описание на изгледа на каталога sys.dm_xe_objects или в потребителския интерфейс за нова сесия, както е показано на фигура 5 (моето подчертаване):
Фигура 5 – Описание на събитието от потребителския интерфейс на новата сесия
Бих препоръчал да сравните производителността на всяко събитие с това предупреждение в описанието, преди действително да го използвате в производствена среда.