我注意到在每日数据仓库构建中有一个运行时间相对较长(20 分钟以上)的自动更新统计操作。涉及的表是
CREATE TABLE [dbo].[factWebAnalytics](
[WebAnalyticsId] [bigint] IDENTITY(1,1) NOT NULL,
[MarketKey] [int] NOT NULL CONSTRAINT [DF_factWebAnalytics_MarketKey] DEFAULT ((-1)),
/*Other columns removed*/
CONSTRAINT [PK_factWebAnalytics] PRIMARY KEY CLUSTERED
(
[MarketKey] ASC,
[WebAnalyticsId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [MarketKeyPS]([MarketKey])
) ON [MarketKeyPS]([MarketKey])
这是在 Microsoft SQL Server 2012 (SP1) - 11.0.3513.0 (X64) 上运行,因此可写列存储索引不可用。
该表包含两个不同市场密钥的数据。该构建将特定 MarketKey 的分区切换到暂存表,禁用列存储索引,执行必要的写入,重建列存储,然后将其切换回。
更新统计信息的执行计划显示它从表中提取所有行,对它们进行排序,得到严重错误的估计行数并溢出到tempdb
溢出级别 2。
跑步
SELECT [s].[name] AS "Statistic",
[sp].*
FROM [sys].[stats] AS [s]
OUTER APPLY sys.dm_db_stats_properties ([s].[object_id], [s].[stats_id]) AS [sp]
WHERE [s].[object_id] = OBJECT_ID(N'[dbo].[factWebAnalytics]');
演出
如果我明确尝试将该索引的统计数据的样本量减少到其他人使用的样本量
UPDATE STATISTICS [dbo].[factWebAnalytics] [PK_factWebAnalytics] WITH SAMPLE 897667 ROWS
查询再次运行 20 分钟以上,执行计划显示它正在处理所有行,而不是请求的 897,667 样本。
所有这一切结束时生成的统计数据不是很有趣,而且似乎绝对不值得花时间进行全面扫描。
Statistics for INDEX 'PK_factWebAnalytics'.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Name Updated Rows Rows Sampled Steps Density Average Key Length String Index
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PK_factWebAnalytics Jan 22 2016 11:31AM 420072086 420072086 2 0 12 NO 420072086
All Density Average Length Columns
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0.5 4 MarketKey
2.380544E-09 12 MarketKey, WebAnalyticsId
Histogram Steps
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 0 3.441652E+08 0 1
2 0 7.590685E+07 0 1
知道为什么我会遇到这种行为,以及除了使用NORECOMPUTE
这些行为之外我可以采取哪些步骤?
重现脚本在这里。它只是创建一个具有聚簇 PK 和列存储索引的表,并尝试使用较小的样本量更新 PK 统计信息。这不使用分区 - 表明不需要分区方面。然而,上述分区的使用确实使事情变得更糟,因为切换分区然后将其切换回来(即使没有任何其他更改)将使 modification_counter 增加分区中行数的两倍,从而实际上保证统计信息将是被认为陈旧并自动更新。
我已经尝试将非聚集索引添加到表中,如 KB2986627 中所示(两者均未过滤任何行,然后,当失败时,未过滤的 NCI 也没有任何效果)。
重现未显示 build 11.0.6020.0 上的问题行为,升级到 SP3 后,该问题现已修复。
我要尝试的第一件事是将 SQL Server 实例从您现在拥有的带有 QFE 的 SP1 CU16 更新到 SP3 CU1(当前 2012 年版本),然后重新测试以查看行为是否相同。
例如:
修复:UPDATE STATISTICS 对 SQL Server 中具有列存储索引的表执行不正确的采样和处理
...在 SP2 CU2 中首次发布可能是相关的。
也就是说,我不确定 2012 columnstore 是否支持 tablesample,这是抽样统计信息所必需的。一旦问题中有 repro,我将更新此答案。