SQL server更新统计信息

在关注更新统计信息时,请牢记以下几点(摘自“ 重建索引与更新统计信息”(本杰明·内瓦雷斯)

  1. 默认情况下,该UPDATE STATISTICS语句仅使用表记录的样本。使用UPDATE STATISTICS WITH FULLSCAN将扫描整个表。

  2. 默认情况下,该UPDATE STATISTICS语句同时更新索引和列统计信息。使用该COLUMNS选项将仅更新列统计信息。使用该INDEX选项将仅更新索引统计信息。

  3. 重建索引(例如,通过使用)ALTER INDEX … REBUILD也将以等同于使用的方式更新索引统计信息,WITH FULLSCAN 除非 对该表进行了分区,在这种情况下,仅对统计信息进行采样(适用于SQL Server 2012及更高版本)。

  4. 使用手动创建的统计信息CREATE STATISTICS不会通过任何ALTER INDEX ... REBUILD操作更新,包括ALTER TABLE ... REBUILDALTER TABLE ... REBUILD如果正在重建的表上定义了聚集索引,则不会更新聚集索引的统计信息。

  5. 重新组织索引(例如使用)ALTER INDEX … REORGANIZE不会更新任何统计信息。

简短的答案是您需要用于UPDATE STATISTICS更新列统计信息,而索引重建将仅更新索引统计信息。您可以使用UPDATE STATISTICS (tablename) WITH FULLSCAN;语法强制更新表上的所有统计信息,包括索引统计信息和手动创建的统计信息。

以下代码说明了上述封装的规则:

首先,我们将创建一个包含几列和一个聚集索引的表:

USE tempdb;

IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;

CREATE TABLE dbo.SomeTable
(
    rn int NOT NULL IDENTITY(1,1)
        CONSTRAINT pk
        PRIMARY KEY NONCLUSTERED
    , i int NOT NULL INDEX i 
    , d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);

CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);

CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;

INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;

此查询显示每个统计信息对象的最后更新日期:

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

结果显示尚未发生任何更新,这是正确的,因为我们刚刚创建了表:

╔═══════════════╦═══════════╦═══════════╗
║ObjectName║StatsName║StatsDate║
╠═══════════════╬═══════════╬═══════════╣
║dbo.SomeTable║cx║NULL║
║dbo.SomeTable║i║NULL║
║dbo.SomeTable║pk║NULL║
bo dbo.SomeTable║d║NULL║
╚═══════════════牛皮═══════════牛皮═══════════╝

让我们重建整个表,看看是否更新了统计信息:

ALTER TABLE dbo.SomeTable REBUILD;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ObjectName║StatsName║StatsDate║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║dbo.SomeTable║cx║2018-09-17 14:09:13.590║
║dbo.SomeTable║i║NULL║
║dbo.SomeTable║pk║NULL║
bo dbo.SomeTable║d║NULL║
╚═══════════════牛皮═══════════牛皮═════════════════════ ════╝

结果显示仅聚集索引统计信息已更新。

接下来,我们执行离散UPDATE STATS操作:

UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

如您所见,我们刚刚更新了d列上的统计信息:

╔═══════════════╦═══════════╦═════════════════════ ════╗
║ObjectName║StatsName║StatsDate║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║dbo.SomeTable║cx║2018-09-17 14:09:13.590║
║dbo.SomeTable║i║NULL║
║dbo.SomeTable║pk║NULL║
║dbo.SomeTable║║-09- 2018-09-17 14:09:13.597║
╚═══════════════牛皮═══════════牛皮═════════════════════ ════╝

现在,我们将更新整个表的统计信息:

UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ObjectName║StatsName║StatsDate║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║dbo.SomeTable║cx║2018-09-17 14:09:13.600║
║dbo.SomeTable║我║2018-09-17 14:09:13.600║
║dbo.SomeTable║pk║2018-09-17 14:09:13.603║
║dbo.SomeTable d║-09- 2018-09-17 14:09:13.607║
╚═══════════════牛皮═══════════牛皮═════════════════════ ════╝

如您所见,确定所有统计信息均得到更新的唯一方法是手动更新每个统计信息,或使用来更新整个表格UPDATE STATISTICS (table);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值