views:

582

answers:

3

Do we need to Update table statistics after calling Truncate table or it gets updated automatically?

Q: Do we need to call "UPDATE STATISTICS" after truncating a table?

+6  A: 

It depends on how your administrator has configured statistics. The usual approach would be a weekly maintenance job. Then you could either wait for the job to run, or update the statistics manually.

There's also the option to automatically update statistics:

When the automatic update statistics option, AUTO_UPDATE_STATISTICS, is on, the query optimizer determines when statistics might be out-of-date and then updates them when they are used by a query.

That would probably recalculate after a truncate.

You can turn on auto-updates like:

ALTER DATABASE AdventureWorks
    SET AUTO_UPDATE_STATISTICS ON;

And to update statistics manually:

UPDATE STATISTICS Sales.SalesOrderDetail

To verify the current age of your statistics, run:

SELECT 
    object_name = Object_Name(ind.object_id),
    IndexName = ind.name,
    StatisticsDate = STATS_DATE(ind.object_id, ind.index_id)
FROM SYS.INDEXES ind
order by STATS_DATE(ind.object_id, ind.index_id) desc
Andomar
(+1) Thanks Andomar. Are there any cons of keeping Auto Update statistics on...OR we can keep it by default? How do I know if it is on my system? (sorry I am not an admin, I have all the access though)
noob.spt
@noob2487: Auto update statistics might impact performance. For example if you have a high load while updating a big table, updating statistics would add even more load. However, in 99% of cases, enabling auto update is an excellent choice.
Andomar
Got it. In my case I have around 100K records to be loaded just after truncating these tables. So better I will have AutoUpdate disabled. Is there a way to find whether it is enabled or disabled?
noob.spt
+1  A: 

As you have no data it will be meaningless until the data gets inserted and then you would look to update the stats.

Dont forget you can auto update stats as well as running and update statistics job daily/weekly etc...

If there is still a major concern about it,j ust truncate and then update the stats on the table.

kevchadders
(+1) Yes thats correct. The statistics will be meaningless as there is no data, or you can say they would be "incorrect". So, I was afraid how those incorrect statistics gonna affect performance once i start inserting data in the table.
noob.spt
The engine would look at statistics to make the plan. It will see that the carefully crafted plan is 'meaningless' only when it actually tries to run it and ... finds no data. So statistics are very important to an empty table: is the statistics that tell optimizer that the table is empty.
Remus Rusanu
+4  A: 

Stats are not automatically updated until the stats are needed again. aka, the TRUNCATE does not do it. So "No".

The original answer was "Yes" because it's not automatic as part of TRUNCATE. It depends how you read the question :-)

Remember, statistics are updated automatically when needed by a query (eg number of row change). From "Index Statistics" in BOL

A statistics update is initiated whenever the statistics used in a query execution plan fail a test for current statistics

One way to verify using STATS_DATE...

SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id)
FROM
   sys.indexes 
WHERE
   object_id = OBJECT_ID('MyTruncatedTable')


Edit: I wanted to make I sure :-)

You'll see stats are only updated by the SELECT statements, not the INSERT, DELETE or TRUNCATE

IF OBJECT_ID('dbo.foo') IS NOT NULL DROP TABLE dbo.foo
CREATE TABLE dbo.foo (
    bar int NOT NULL IDENTITY (1, 1) PRIMARY KEY,
    thing int NOT NULL
)
CREATE INDEX IX_thing ON dbo.foo (thing)

INSERT dbo.foo (thing) SELECT c1.object_id FROM sys.columns c1, sys.columns c2
SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id) AS AfterLoad
FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.foo')

SELECT DISTINCT thing FROM dbo.foo ORDER BY thing DESC
SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id) AS AfterFirstQuery
FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.foo')

DELETE TOP (50000) dbo.foo
SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id) AS AfterDelete
FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.foo')

SELECT DISTINCT thing FROM dbo.foo ORDER BY thing DESC
SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id) AS After2ndQuery
FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.foo')

TRUNCATE TABLE dbo.foo
SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id) AS AfterTruncate
FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.foo')

SELECT DISTINCT thing FROM dbo.foo ORDER BY thing DESC
SELECT
   name AS index_name, 
   STATS_DATE(object_id, index_id) AS After3rdQuery
FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.foo')
gbn
(+1) Thanks gbn!
noob.spt
@gbn: I executed this query as it is. It is running for last 12 mins. Is it stuck in some lock? How much time should it take? Guess I need to kill it now.
noob.spt
Sorry, it ran in 10 secs on my Virtual PC SQL 2008 instance. My DB is empty though and gave 238k rows, so it could be simply too many rows...
gbn
@gbn: Ok. It finally finished executing after 12:25 mins. According to this statistics were not updated both after delete or truncate. So it seems I need to call "UPDATE STATISTICS". Is it correct?
noob.spt
No need, the engine will realise this for the next SELECT
gbn
In After3rdQuery, IX_thing came as null. What does that suppose to mean?
noob.spt
No rows = no stats!
gbn
Cool. Thanks for the perfect analysis.
noob.spt
Could you modify your answer a little to go along with the question. 'Yes' in the start looks wrong. Please update it for me to mark it as answer.Thank You.
noob.spt
@noob2487: done, with extra comments. It depends how you read the question :-)
gbn
Thanks a lot. Just wanted to make sure its not confusing for anyone referring to this question in future :)
noob.spt