sql-server – 重新索引更新统计信息吗?

前端之家收集整理的这篇文章主要介绍了sql-server – 重新索引更新统计信息吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
过去一周我一直在做MS10775A课程,而且培训师无法可靠回答的一个问题是:

Does a re-index update the statistics?

我们在网上发现了讨论,认为它确实存在,而事实并非如此.

解决方法

在关注更新统计数据时,您可以牢记以下几点(从 Rebuilding Indexes vs. Updating Statistics (Benjamin Nevarez)复制)

>默认情况下,UPDATE STATISTICS语句仅使用表的记录样本.使用UPDATE STATISTICS WITH FULLSCAN将扫描整个表.
>默认情况下,UPDATE STATISTICS语句更新索引和列统计信息.使用COLUMNS选项将仅更新列统计信息.使用INDEX选项将仅更新索引统计信息.
>重建索引,例如使用ALTER INDEX … REBUILD也将使用WITH FULLSCAN更新索引统计信息,除非the table is partitioned,in which case the statistics are only sampled(适用于sql Server 2012及更高版本).
>使用CREATE STATISTICS手动创建的统计信息不会被任何ALTER INDEX … REBUILD操作更新,包括ALTER TABLE … REBUILD. ALTER TABLE …如果正在重建的表上定义了聚簇索引,则REBUILD会更新聚簇索引的统计信息.
>重新组织索引,例如使用ALTER INDEX … REORGANIZE不会更新任何统计信息.

简短的回答是,您需要使用UPDATE STATISTICS来更新列统计信息,并且索引重建将仅更新索引统计信息.您可以使用UPDATE STATISTICS(tablename)WITH FULLSCAN强制更新表上的所有统计信息,包括index-stats和手动创建的统计信息;句法.

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

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

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      ║
║ dbo.SoMetable ║ d         ║ NULL      ║
╚═══════════════╩═══════════╩═══════════╝

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

ALTER TABLE dbo.SoMetable REBUILD;

SELECT ObjectName = sc.name + N'.' + o.name,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                    ║
║ dbo.SoMetable ║ d         ║ NULL                    ║
╚═══════════════╩═══════════╩═════════════════════════╝

结果显示只更新了聚簇索引统计信息.

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

UPDATE STATISTICS dbo.SoMetable(d) WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name,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 ║ d         ║ 2018-09-17 14:09:13.597 ║
╚═══════════════╩═══════════╩═════════════════════════╝

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

UPDATE STATISTICS dbo.SoMetable WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name,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 ║ i         ║ 2018-09-17 14:09:13.600 ║
║ dbo.SoMetable ║ pk        ║ 2018-09-17 14:09:13.603 ║
║ dbo.SoMetable ║ d         ║ 2018-09-17 14:09:13.607 ║
╚═══════════════╩═══════════╩═════════════════════════╝

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

猜你在找的MsSQL相关文章