Correct SQL Server TempDB Spills in Query Plans Caused by Outdated Statistics

转载 2016年08月31日 10:24:34

https://www.mssqltips.com/sqlservertip/4132/correct-sql-server-tempdb-spills-in-query-plans-caused-by-outdated-statistics/


Problem

Statistics are an integral part of SQL Server and query performance. In short, the query optimizer uses statistics to create query plans that will improve the overall performance of the queries ran. Each statistic object is created on a list of one or more table columns and includes a histogram displaying the distribution of values in the first column. The histogram can have up to 200 steps, but no more regardless of the number of rows in the column or index. Unfortunately, I have seen a warning in my query plan that reads: "Operator used tempdb to spill data during execution with spill level 1". How do I address this warning?

Solution

In this tip we’ll take a look at one specific performance issue that you might find in an execution plan of a query which is "Operator used tempdb to spill data during execution with spill level 1". If you’ve ever noticed the following warning, then this tip is for you:

Operator used tempdb spill data during execution with spill level 1

Within the AdventureWorks2014 DB, I’ll use the following query for my example:

SELECT BusinessEntityID, FirstName, LastName, EmailPromotion
FROM [AdventureWorks2014].[Person].[Person]
WHERE EmailPromotion > 0
ORDER BY LastName
        

Looking at this query I can already tell contention may be present so I’ll go ahead and add a covering index:

CREATE NONCLUSTERED INDEX [IX_Person_EmailPromotion_INCLUDES]
ON [Person].[Person] ([EmailPromotion])
INCLUDE ([BusinessEntityID],[FirstName],[LastName])
        

When adding the index above, statistics were automatically created and updated. Since the addition of this index I’ve added a few thousand rows to the Person table.

Let’s run the query and make sure the “Include Actual Execution Plan” button is selected.

Include Actual Execution Plan in SQL Server Management Studio

After the query executes let’s take a look at the execution plan by clicking on the tab in the Results pane:

SQL Server Management Studio Execution Plan

One of the first things you’ll probably notice is the warning sign on the Sort operation. If we hover our mouse over this operator you’ll see more information including the “Warnings: Operator used tempdb to spill data during the execution with spill level 1”

SQL Server Sort operator that used tempdb instead of memory

These warnings were added to SQL Server Management Studio 2012, so if you’re using an older version you may not see this. The spill data to TempDB warning means that the query was not granted enough memory to finish the operation and spilled over into the TempDB to complete the operation. We all know reading from memory is much faster than reading from disk and this is exactly what is happening here. The query read as much as it could from memory before moving over to the TempDB disk.

Let’s look into this further. Hover over the arrow leading to the Sort operation to view the Actual Number of Rows and Estimated Number of Rows:

Estimated Number of Rows vs Actual Number of Rows has a large discrepancy

Aha! The SQL Server database engine only estimated this query would return 568,136 rows, but we actually returned 1,128,192 rows. Seeing this type of discrepancy usually means that statistics are out of date.

Let’s run DBCC SHOW_STATISTICS against our new index to view the histogram:

DBCC SHOW_STATISTICS ('Person.Person', IX_Person_EmailPromotion_INCLUDES)
        


DBCC SHOW_STATISTICS for the recently created index

As you can see from the previous screenshot, DBCC SHOW_STATISTICS returns 3 different result sets.

  • General information about the statistics object
  • Density vector
  • Histogram

We’re going to concentrate on the general information and histogram result sets for this tip. As you can see from the general information set, rows equal 319,552 and rows sampled equals 68,991

Density vector for the index with a discrepancy between the rows and rows sampled

When we run the following query you’ll notice that there are a lot more records than the general information results are displaying:

SELECT COUNT(EmailPromotion)
FROM [AdventureWorks2014].[Person].[Person]
        


Row count

Also, you can see from the column RANGE_HI_KEY, there are 177,518 records where the EmailPromotion column equals 0.

RANGE_HI_KEY values and the associated number of rows in the EQ_ROWS column

If you run the following query, however, you’ll see that 1,428,224 records exist where EmailPromotion is equal to 0:

SELECT COUNT(*)
FROM [AdventureWorks2014].[Person].[Person]
WHERE EmailPromotion = 0
        


All rows with the EmailPromotion of zero

Let’s update this statistic with FULLSCAN by running the following statement:

UPDATE STATISTICS Person.Person IX_Person_EmailPromotion_INCLUDES WITH FULLSCAN
        

Now when we run DBCC SHOW_STATISTICS we’ll notice that rows and rows sampled in the general information results are correct. We’ll also see that 1,428,224 records exist for the RANGE_HI_KEY 0. These are the results we were expecting to get.

Results of Rows and Rows Sampled UPDATE STATISTICS with FULLSCAN

Let’s run our query again and look at the execution plan:

Final query plan with the updated statistics

Yes! The warning is gone.

Next Steps
  • When a query is compiled SQL Server does not look at the data in the table or index. It uses statistics to estimate the number of rows that will be returned and that will determine the execution plan. This is why it’s important to keep statistics updated on a regular basis and included as part of your regular maintenance schedule.

举报

相关文章推荐

Correct SQL Server TempDB Spills in Query Plans Caused by Outdated Statistics

https://www.mssqltips.com/sqlservertip/4132/correct-sql-server-tempdb-spills-in-query-plans-caused-b...

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Query was empty

1 错误描述 at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHa...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Query was empty

1、错误描述[ERROR:]2015-07-15 20:22:55,599 [插入失败] org.hibernate.exception.SQLGrammarException: error exe...

SQL Server Statistics AUTO_UPDATE_STATISTICS

It is known that the necessities for SQL Server auto updating statistics is as followed If the ...

SQL SERVER STATISTICS

些信息中各个字段的意义,都有其相应的意义(以下来自引用): 扫描计数(Scan Count):在查询中涉及到的表被访问的次数。在我们的例子中,其中的表只被访问了1次,由于查询中不包括连接命令,这一信...

SQL Server中tempdb的管理

资料来自: http://blogs.msdn.com/b/sqlserverstorageengine/archive/tags/tempdb/ http://blogs.msdn.com/b/...

org.springframework.beans.factory.BeanCreationException: Error creating bean with name

org.springframework.beans.factory.BeanCreationException: Error creating bean with name

Caused by: java.lang.NoSuchMethodError: javax.persistence.spi.PersistenceUnitInfo.getValidationMode(

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManage...

Caused by: java.sql.SQLException: ORA-01795: 列表中的最大表达式数为 1000解决方案

这个原因在于Oracle语法限制,in内数量必须小于1000,故采取满1000分割用OR连接,下面是解决方案: /** * Example: List sqhlist=[''aa''"bb""c...

Caused by: java.lang.ClassNotFoundException[android的终极解决错误]

Caused by: java.lang.ClassNotFoundException:XXXXX    in loader dalvik.system.PathClassLoader[/data/a...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)