截断表和更新统计信息

时间:2009-11-13 16:15:01

标签: sql sql-server sql-server-2005 performance

我们是否需要在调用Truncate表后更新表统计信息,否则它会自动更新?

问:截断表后我们是否需要调用“UPDATE STATISTICS”?

3 个答案:

答案 0 :(得分:7)

这取决于管理员配置统计信息的方式。通常的方法是每周维护工作。然后,您可以等待作业运行,也可以手动更新统计信息。

还有automatically update statistics的选项:

  

自动更新统计信息时   选项AUTO_UPDATE_STATISTICS已启用,   查询优化器确定何时   统计数据可能已过时   然后在使用时更新它们   通过查询。

这可能会在截断后重新计算。

您可以启用自动更新,例如:

ALTER DATABASE AdventureWorks
    SET AUTO_UPDATE_STATISTICS ON;

手动update statistics

UPDATE STATISTICS Sales.SalesOrderDetail

要验证统计信息的当前年龄,请运行:

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

答案 1 :(得分:7)

在再次需要统计数据之前,统计信息不会自动更新。又名,TRUNCATE没有这样做。 所以“不”。

原始答案是“是”,因为它不是TRUNCATE的一部分。这取决于你如何阅读这个问题: - )

请记住,查询需要时会自动更新统计信息(例如,行数更改)。来自BOL中的“Index Statistics

  

只要查询执行计划中使用的统计信息未通过当前统计信息的测试

,就会启动统计信息更新

使用STATS_DATE验证的一种方法......

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


修改:我想确定一下: - )

您将看到统计信息仅由SELECT语句更新,而不是INSERT,DELETE或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')

答案 2 :(得分:1)

由于你有没有数据,在插入数据之前它将毫无意义,然后你会想要更新统计数据。

不要忘记您可以自动更新统计数据以及每天/每周运行和更新统计数据等...

如果仍有一个主要问题,请截断然后更新表格中的统计数据。