Warning: Constant WP_TEMP_DIR already defined in /var/www/html/blogs/joe/wp-config.php on line 93

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/blogs/joe/wp-config.php:93) in /var/www/html/blogs/joe/wp-includes/rest-api/class-wp-rest-server.php on line 1902
{"id":462,"date":"2012-12-12T01:15:05","date_gmt":"2012-12-12T01:15:05","guid":{"rendered":"\/blogs\/joe\/post\/Detecting-Cardinality-Estimate-Issues-with-sysdm_exec_query_stats.aspx"},"modified":"2013-12-29T19:15:21","modified_gmt":"2013-12-30T03:15:21","slug":"detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/","title":{"rendered":"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats"},"content":{"rendered":"

SQL Server 2008 R2 SP1 and SQL Server 2012 RTM+ includes actual row count statistics in the sys.dm_exec_query_stats dynamic management view.\u00a0 This includes the total_rows, last_rows, min_rows and max_rows columns, which are intuitively named.<\/p>\n

One potential use of the row statistics data is to detect cardinality estimate issues where the actual count of rows is significantly different from the query plan\u2019s estimated rows.\u00a0 While I can see using this information as a valid approach, there are limits, and I\u2019ll walk through them in this post.<\/p>\n

To illustrate the use cases, I\u2019m going to use the Credit<\/a> database to execute three different queries.\u00a0 I\u2019ll show you the plan tree tab from SQL Sentry Plan Explorer<\/a> for each query.<\/p>\n

Query 1: No Cardinality Estimate Issue<\/strong><\/p>\n

\r\nSELECT  region.region_name,\r\n        member.lastname,\r\n        member.firstname,\r\n        member.member_no\r\nFROM    dbo.member\r\nINNER JOIN dbo.region\r\n        ON region.region_no = member.region_no\r\nWHERE   region.region_no = 9;\r\nGO\r\n<\/pre>\n
<\/pre>\n

The plan:<\/p>\n

\"image\"<\/a><\/p>\n

For each operation in this query, the estimated rows match the actual rows.<\/p>\n

Query 2: Cardinality Estimate Issue, Leaf-Level + Final Operator<\/strong><\/p>\n

\r\nDECLARE @Column INT = 2,\r\n    @Value INT = 10;\r\n\r\nSELECT  [member].[member_no],\r\n        [member].[street],\r\n        [member].[city],\r\n        [charge].[charge_no],\r\n        [charge].[provider_no],\r\n        [charge].[category_no],\r\n        [charge].[charge_dt],\r\n        [charge].[charge_amt],\r\n        [charge].[charge_code]\r\nFROM    [dbo].[charge]\r\nINNER JOIN [dbo].[member]\r\n        ON [member].[member_no] = [charge].[member_no]\r\nWHERE   CHOOSE(@Column, [charge].[provider_no], [charge].[category_no]) = @Value;\r\nGO\r\n\r\n<\/pre>\n

The plan:<\/p>\n

\"image\"<\/a><\/p>\n

Unlike the previous query, for this query we have leaf-level estimated vs. actual row count skews and skews that flow up to the final operation.<\/p>\n

Query 3: Cardinality Estimate Leaf-Level Skew and No Skew for Root Operator<\/strong><\/p>\n

\r\nSELECT TOP (1000)\r\n        [member].[member_no],\r\n        [member].[lastname],\r\n        [member].[firstname],\r\n        [region].[region_no],\r\n        [region].[region_name],\r\n        [provider].[provider_name],\r\n        [category].[category_desc],\r\n        [charge].[charge_no],\r\n        [charge].[provider_no],\r\n        [charge].[category_no],\r\n        [charge].[charge_dt],\r\n        [charge].[charge_amt],\r\n        [charge].[charge_code]\r\nFROM    [dbo].[provider]\r\nINNER JOIN [dbo].[charge]\r\n        ON [provider].[provider_no] = [charge].[provider_no]\r\nINNER JOIN [dbo].[member]\r\n        ON [member].[member_no] = [charge].[member_no]\r\nINNER JOIN [dbo].[region]\r\n        ON [region].[region_no] = [member].[region_no]\r\nINNER JOIN [dbo].[category]\r\n        ON [category].[category_no] = [charge].[category_no];\r\nGO\r\n\r\n<\/pre>\n

The plan:<\/p>\n

\"image\"<\/a><\/p>\n

For this third query, we see leaf-level skews (and intermediate-level for the Hash Match), but then the root of the plan does NOT have a skew (estimated 1,000 vs. actual 1,000).<\/p>\n

Detecting Issues<\/strong><\/p>\n

So in my next query, I pull the estimated rows out from the query execution plan of the three queries and compare it to the last actual row count values from sys.dm_exec_query_stats (and I\u2019m keeping this example query as simple as possible):<\/p>\n

\r\nSELECT  t.text,\r\n\t\tp.[query_plan],\r\n\t\ts.[last_execution_time],\r\n\t\tp.[query_plan].value('(\/\/@EstimateRows)[1]', 'varchar(128)') AS [estimated_rows],\r\n\t\ts.[last_rows]\r\nFROM    sys.[dm_exec_query_stats] AS [s]\r\nCROSS APPLY sys.[dm_exec_sql_text](sql_handle) AS [t]\r\nCROSS APPLY sys.[dm_exec_query_plan](plan_handle) AS [p]\r\nWHERE   DATEDIFF(mi, s.[last_execution_time], GETDATE()) < 1\r\nGO\r\n<\/pre>\n

The results are as follows:<\/p>\n

\"image\"<\/a><\/p>\n

So what do we see here?\u00a0 We show a final skew for just one query (Query #2).\u00a0 The other two queries show no final skew.\u00a0 For Query #1 \u2013 that is an accurate assessment, but for Query #3 the underlying skew is hidden since we\u2019re only looking at the final operator estimated rows vs. actual.\u00a0 So our actual row count stats are still useful \u2013 but for only one specific skew scenario.<\/p>\n

Why Does this Matter?<\/strong><\/p>\n

Even if the query optimizer estimates final row counts accurately, the leaf-level skews can drive performance issues.\u00a0 For example \u2013 for leaf-level or intermediate skews, you may be under-estimating memory grants sizes (risk of spills) or actually over-estimating memory grant sizes (potential concurrency issues for larger grant queries).\u00a0 Another example may be the seek vs scan decision, with unnecessary I\/O being driven by leaf-level skews.<\/p>\n

So to summarize, the additional sys.dm_exec_query_stats data is useful for situations where we can detect the skew at the root of the query plan, but it doesn\u2019t help you identify leaf-level and intermediate-level skews.<\/p>\n","protected":false},"excerpt":{"rendered":"

SQL Server 2008 R2 SP1 and SQL Server 2012 RTM+ includes actual row count statistics in the sys.dm_exec_query_stats dynamic management view.\u00a0 This includes the total_rows, last_rows, min_rows and max_rows columns, which are intuitively named. One potential use of the row statistics data is to detect cardinality estimate issues where the actual count of rows is […]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42,28],"tags":[],"class_list":["post-462","post","type-post","status-publish","format-standard","hentry","category-cardinality-estimation","category-performance"],"yoast_head":"\nDetecting Cardinality Estimate Issues with sys.dm_exec_query_stats - Joe Sack<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats - Joe Sack\" \/>\n<meta property=\"og:description\" content=\"SQL Server 2008 R2 SP1 and SQL Server 2012 RTM+ includes actual row count statistics in the sys.dm_exec_query_stats dynamic management view.\u00a0 This includes the total_rows, last_rows, min_rows and max_rows columns, which are intuitively named. One potential use of the row statistics data is to detect cardinality estimate issues where the actual count of rows is […]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/\" \/>\n<meta property=\"og:site_name\" content=\"Joe Sack\" \/>\n<meta property=\"article:published_time\" content=\"2012-12-12T01:15:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2013-12-30T03:15:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-content\/uploads\/windows-live-writer\/comparing\/4dd19936\/image_thumb.png\" \/>\n<meta name=\"author\" content=\"Joseph Sack\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joseph Sack\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/\",\"name\":\"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats - Joe Sack\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/#website\"},\"datePublished\":\"2012-12-12T01:15:05+00:00\",\"dateModified\":\"2013-12-30T03:15:21+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/#\/schema\/person\/533eb0113a15fb5a6e8067a49e4ae648\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cardinality Estimation\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/category\/cardinality-estimation\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/\",\"name\":\"Joe Sack\",\"description\":\"SQL Server Performance Tuning, High Availability and Disaster Recovery Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/#\/schema\/person\/533eb0113a15fb5a6e8067a49e4ae648\",\"name\":\"Joseph Sack\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a4b39a7719a6bfff1add3ec00527810734579ee114d6d983e8e68f937b77be96?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a4b39a7719a6bfff1add3ec00527810734579ee114d6d983e8e68f937b77be96?s=96&d=mm&r=g\",\"caption\":\"Joseph Sack\"},\"description\":\"Joe Sack is a Principal Consultant with SQLskills. He has worked as a SQL Server professional since 1997 and has supported and developed for SQL Server environments in financial services, IT consulting, manufacturing, retail and the real estate industry. Prior to joining SQLskills he worked at Microsoft as a Premier Field Engineer supporting very large enterprise customer environments. He was responsible for providing deep SQL Server advisory services, training, troubleshooting and ongoing solutions guidance. His areas of expertise include performance tuning, scalability, T-SQL development and high-availability. In 2006 Joe earned the \u201cMicrosoft Certified Master: SQL Server 2005\u201d certification and in 2008 he earned the \u201cMicrosoft Certified Master: SQL Server 2008\u201d certification. In 2009 he took over responsibility for the entire SQL Server Microsoft Certified Master program and held that post until 2011. He was given the SQL Server MVP award in 2013.\",\"sameAs\":[\"http:\/\/3.209.169.194\/blogs\/joe\",\"https:\/\/twitter.com\/https:\/\/twitter.com\/josephsack\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/joe\/author\/joe\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats - Joe Sack","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/","og_locale":"en_US","og_type":"article","og_title":"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats - Joe Sack","og_description":"SQL Server 2008 R2 SP1 and SQL Server 2012 RTM+ includes actual row count statistics in the sys.dm_exec_query_stats dynamic management view.\u00a0 This includes the total_rows, last_rows, min_rows and max_rows columns, which are intuitively named. One potential use of the row statistics data is to detect cardinality estimate issues where the actual count of rows is […]","og_url":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/","og_site_name":"Joe Sack","article_published_time":"2012-12-12T01:15:05+00:00","article_modified_time":"2013-12-30T03:15:21+00:00","og_image":[{"url":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-content\/uploads\/windows-live-writer\/comparing\/4dd19936\/image_thumb.png"}],"author":"Joseph Sack","twitter_misc":{"Written by":"Joseph Sack","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/","url":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/","name":"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats - Joe Sack","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/#website"},"datePublished":"2012-12-12T01:15:05+00:00","dateModified":"2013-12-30T03:15:21+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/#\/schema\/person\/533eb0113a15fb5a6e8067a49e4ae648"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/detecting-cardinality-estimate-issues-with-sys-dm_exec_query_stats\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/joe\/"},{"@type":"ListItem","position":2,"name":"Cardinality Estimation","item":"https:\/\/www.sqlskills.com\/blogs\/joe\/category\/cardinality-estimation\/"},{"@type":"ListItem","position":3,"name":"Detecting Cardinality Estimate Issues with sys.dm_exec_query_stats"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/joe\/","name":"Joe Sack","description":"SQL Server Performance Tuning, High Availability and Disaster Recovery Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/joe\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/#\/schema\/person\/533eb0113a15fb5a6e8067a49e4ae648","name":"Joseph Sack","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/joe\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a4b39a7719a6bfff1add3ec00527810734579ee114d6d983e8e68f937b77be96?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a4b39a7719a6bfff1add3ec00527810734579ee114d6d983e8e68f937b77be96?s=96&d=mm&r=g","caption":"Joseph Sack"},"description":"Joe Sack is a Principal Consultant with SQLskills. He has worked as a SQL Server professional since 1997 and has supported and developed for SQL Server environments in financial services, IT consulting, manufacturing, retail and the real estate industry. Prior to joining SQLskills he worked at Microsoft as a Premier Field Engineer supporting very large enterprise customer environments. He was responsible for providing deep SQL Server advisory services, training, troubleshooting and ongoing solutions guidance. His areas of expertise include performance tuning, scalability, T-SQL development and high-availability. In 2006 Joe earned the \u201cMicrosoft Certified Master: SQL Server 2005\u201d certification and in 2008 he earned the \u201cMicrosoft Certified Master: SQL Server 2008\u201d certification. In 2009 he took over responsibility for the entire SQL Server Microsoft Certified Master program and held that post until 2011. He was given the SQL Server MVP award in 2013.","sameAs":["http:\/\/3.209.169.194\/blogs\/joe","https:\/\/twitter.com\/https:\/\/twitter.com\/josephsack"],"url":"https:\/\/www.sqlskills.com\/blogs\/joe\/author\/joe\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/posts\/462","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/comments?post=462"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/posts\/462\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/media?parent=462"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/categories?post=462"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/joe\/wp-json\/wp\/v2\/tags?post=462"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}