sql-server – 重新索引更新统计信息吗?
过去一周我一直在做MS10775A课程,而且培训师无法可靠回答的一个问题是:
我们在网上发现了讨论,认为它确实存在,而事实并非如此. 解决方法在关注更新统计数据时,您可以牢记以下几点(从 Rebuilding Indexes vs. Updating Statistics (Benjamin Nevarez)复制)>默认情况下,UPDATE STATISTICS语句仅使用表的记录样本.使用UPDATE STATISTICS WITH FULLSCAN将扫描整个表. 简短的回答是,您需要使用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);更新整个表. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |