{"id":2434,"date":"2019-07-02T16:00:17","date_gmt":"2019-07-02T14:00:17","guid":{"rendered":"https:\/\/www.sqlinthewild.co.za\/?p=2434"},"modified":"2019-06-29T23:49:19","modified_gmt":"2019-06-29T21:49:19","slug":"a-new-way-of-getting-the-actual-execution-plan","status":"publish","type":"post","link":"https:\/\/www.sqlinthewild.co.za\/index.php\/2019\/07\/02\/a-new-way-of-getting-the-actual-execution-plan\/","title":{"rendered":"A new way of getting the actual execution plan"},"content":{"rendered":"\n<p>Getting the actual execution plan, that is the plan with run-time statistics for  a query from an application has always been a little difficult. It\u2019s fine if you  can get the query running in Management Studio and reproducing the behaviour  from the app, but that can be difficult. <\/p>\n\n\n\n<p>There\u2019s the query_post_execution_showplan event in Extended Events, but that\u2019s a  pretty heavy event and not something that I\u2019d like to run on a busy server.<\/p>\n\n\n\n<p>No more! SQL 2019 adds a new plan-related function to get the last actual plan  for a query: sys.dm_exec_query_plan_stats.<\/p>\n\n\n\n<p>The function is not available by default, Last_Query_Plan_Stats database \nscoped configuration has to be set&nbsp; to allow it to run, and it\u2019s going to add \nsome overhead, how much is still to be determined. <\/p>\n\n\n\n<p>ALTER DATABASE SCOPED CONFIGURATION SET LAST_QUERY_PLAN_STATS = ON<\/p>\n\n\n\n<p>It\u2019s a function which takes a parameter of a plan handle or a sql handle.  Hence it can be used alone, or it can be on the right-hand side of an apply from  any table or DMV that has a plan handle or sql handle in it. As an example it  can be used with QueryStore.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"165\" data-attachment-id=\"2435\" data-permalink=\"https:\/\/www.sqlinthewild.co.za\/index.php\/2019\/07\/02\/a-new-way-of-getting-the-actual-execution-plan\/functionoutput\/\" data-orig-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput.png\" data-orig-size=\"1219,197\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"FunctionOutput\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-300x48.png\" data-large-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-1024x165.png\" src=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-1024x165.png\" alt=\"\" class=\"wp-image-2435\" srcset=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-1024x165.png 1024w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-300x48.png 300w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-768x124.png 768w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput-765x124.png 765w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/FunctionOutput.png 1219w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nWITH hist\nAS (SELECT q.query_id, \n           q.query_hash,\n           MAX(rs.max_duration)  AS MaxDuration\n    FROM \n        sys.query_store_query q INNER JOIN sys.query_store_plan p ON q.query_id = p.query_id\n        INNER JOIN sys.query_store_runtime_stats rs ON p.plan_id = rs.plan_id\n        INNER JOIN sys.query_store_runtime_stats_interval rsi ON rs.runtime_stats_interval_id = rsi.runtime_stats_interval_id\n    WHERE start_time &lt; DATEADD(HOUR, -1, GETDATE())\n    GROUP BY q.query_id, query_hash),\nrecent\nAS (SELECT q.query_id, \n           q.query_hash,\n           MAX(rs.max_duration)  AS MaxDuration\n    FROM \n        sys.query_store_query q INNER JOIN sys.query_store_plan p ON q.query_id = p.query_id\n        INNER JOIN sys.query_store_runtime_stats rs ON p.plan_id = rs.plan_id\n        INNER JOIN sys.query_store_runtime_stats_interval rsi ON rs.runtime_stats_interval_id = rsi.runtime_stats_interval_id\n    WHERE start_time &gt; DATEADD(HOUR, -1, GETDATE())\n    GROUP BY q.query_id, query_hash),\nregressed_queries \nAS (\n    SELECT hist.query_id, \n            hist.query_hash\n        FROM hist INNER JOIN recent ON hist.query_id = recent.query_id\n        WHERE recent.MaxDuration &gt; 1.2*hist.MaxDuration\n    )\nSELECT st.text, OBJECT_NAME(st.objectid) AS ObjectName, qs.last_execution_time, qps.query_plan\n    FROM sys.dm_exec_query_stats qs \n        CROSS APPLY sys.dm_exec_sql_text (qs.sql_handle) st\n        OUTER APPLY sys.dm_exec_query_plan_stats(qs.plan_handle) qps\n    WHERE query_hash IN (SELECT query_hash FROM regressed_queries)\n<\/pre><\/div>\n\n\n<p> The above query checks query store for any query that has regressed in  duration  in the last hour (defined as max duration > 120% of  previous max duration)  and pulls the last actual plan for that query  out.  <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"311\" data-attachment-id=\"2436\" data-permalink=\"https:\/\/www.sqlinthewild.co.za\/index.php\/2019\/07\/02\/a-new-way-of-getting-the-actual-execution-plan\/querytogetplan\/\" data-orig-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan.png\" data-orig-size=\"1150,349\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"QueryToGetPlan\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-300x91.png\" data-large-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-1024x311.png\" src=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-1024x311.png\" alt=\"\" class=\"wp-image-2436\" srcset=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-1024x311.png 1024w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-300x91.png 300w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-768x233.png 768w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan-765x232.png 765w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/QueryToGetPlan.png 1150w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And a look at that plan tells me that I have a bad parameter sniffing  problem, a  problem that might have been missed or mis-diagnosed with  only the estimated  plan available.<br><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"557\" data-attachment-id=\"2437\" data-permalink=\"https:\/\/www.sqlinthewild.co.za\/index.php\/2019\/07\/02\/a-new-way-of-getting-the-actual-execution-plan\/parametersniffing\/\" data-orig-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing.png\" data-orig-size=\"1591,866\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ParameterSniffing\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-300x163.png\" data-large-file=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-1024x557.png\" src=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-1024x557.png\" alt=\"\" class=\"wp-image-2437\" srcset=\"https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-1024x557.png 1024w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-300x163.png 300w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-768x418.png 768w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing-765x416.png 765w, https:\/\/www.sqlinthewild.co.za\/wp-content\/uploads\/2019\/06\/ParameterSniffing.png 1591w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Getting the actual execution plan, that is the plan with run-time statistics for a query from an application has always been a little difficult. It\u2019s fine if you can get the query running in Management Studio and reproducing the behaviour&#8230; <a class=\"read-more-button\" href=\"https:\/\/www.sqlinthewild.co.za\/index.php\/2019\/07\/02\/a-new-way-of-getting-the-actual-execution-plan\/\">(Read more)<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[23,15],"tags":[],"class_list":["post-2434","post","type-post","status-publish","format-standard","hentry","category-execution-plans","category-sql-server"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p7h6n-Dg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/posts\/2434","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/comments?post=2434"}],"version-history":[{"count":1,"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/posts\/2434\/revisions"}],"predecessor-version":[{"id":2438,"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/posts\/2434\/revisions\/2438"}],"wp:attachment":[{"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/media?parent=2434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/categories?post=2434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlinthewild.co.za\/index.php\/wp-json\/wp\/v2\/tags?post=2434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}