在 SQL Server 2008 或更高版本中,是UPDATE STATISTICS WITH FULLSCAN单线程操作还是可以使用并行性?如何使用默认采样更新统计信息 - 它可以使用并行性吗?我没有看到指定MAXDOP更新统计信息的选项。
我有几个大桌子。我想通过每周维护计划确保他们的统计数据是最新的。
但是,这样做需要花费太多时间。
如果我指定
WITH SAMPLE 50 PERCENT
Run Code Online (Sandbox Code Playgroud)
SQL Server 然后采样:
BOL对此并不明确。
我正在考虑一种情况,我有两个高密度的列,但这些列不是独立的。
这是我为测试目的而创建的表的定义。
CREATE TABLE [dbo].[StatsTest](
[col1] [int] NOT NULL, --can take values 1 and 2 only
[col2] [int] NOT NULL, --can take integer values from 1 to 4 only
[col3] [int] NOT NULL, --integer. it has not relevance just to ensure that each row is different
[col4] AS ((10)*[col1]+[col2]) --a computed column ensuring that if two rows have different values in col1 or col2 have different values in col4
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
实验数据如下
col1 col2 col3 col4
1 …Run Code Online (Sandbox Code Playgroud) 我在 SQL Server 中有 200 GB 的数据仓库。
对于某些查询,我遇到了非常缓慢的执行时间;例如delete,使用inner join.
在对执行计划进行了一些研究之后,我使用该WITH FULLSCAN选项更新了查询中涉及的 2 个表的统计信息。
查询现在在不到一秒的时间内执行,因此统计信息似乎不是最新的。
我正在考虑禁用auto update statistics数据库并UPDATE STATISTICS在加载数据仓库后手动运行。每天晚上从源 ERP 系统增量加载数据仓库。
我假设auto update statistics在数据仓库场景中不是真的有用吗?相反,在数据加载后手动更新统计数据是否更有意义?
当我这样做时,dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)我会得到报告 ID 18698 的以下结果:

对于此查询:
SELECT *
FROM Reports_Documents
WHERE ReportID = 18698 option (recompile)
Run Code Online (Sandbox Code Playgroud)
我得到一个查询计划,PK_Reports_Documents按预期进行聚集索引搜索。
但让我感到困惑的是估计行数的错误值:

根据这个:
当示例查询 WHERE 子句值等于直方图 RANGE_HI_KEY 值时,SQL Server 将使用直方图中的 EQ_ROWS 列来确定等于的行数
这也是我所期望的方式,但在现实生活中似乎并非如此。我还尝试RANGE_HI_KEY了由提供的直方图中存在的一些其他值,show_statistics并经历了相同的情况。在我的情况下,这个问题似乎导致某些查询使用非常不理想的执行计划,导致执行时间为几分钟,而我可以通过查询提示在 1 秒内运行它。
总而言之:有人可以解释一下为什么EQ_ROWS直方图没有用于估计的行数,不正确的估计来自哪里?
更多(可能有用)信息:
PK_Reports_Documents是一个组合PK,由ReportID INT和DocumentID CHAR(8)该查询似乎总共加载了 5 个不同的统计对象,所有这些对象都包含ReportID表中的 + 一些其他列。它们都已新鲜更新。RANGE_HI_KEY下表中是直方图中的最高上限列值。
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| name | stats_id | auto_created | user_created | Leading column Type …Run Code Online (Sandbox Code Playgroud) 我注意到在日常数据仓库构建中运行时间相对较长(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])
Run Code Online (Sandbox Code Playgroud)
它在 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 …Run Code Online (Sandbox Code Playgroud) 我试图了解统计抽样是如何工作的,以及以下是否是抽样统计更新的预期行为。
我们有一个按日期分区的大表,有几十亿行。分区日期是先前的营业日期,因此是升序键。我们只将前一天的数据加载到该表中。
数据加载在夜间运行,因此在 4 月 8 日星期五,我们加载了 7 日的数据。
每次运行后,我们都会更新统计信息,尽管采取了一个样本,而不是一个FULLSCAN.
也许我太天真了,但我希望 SQL Server 识别范围中的最高键和最低键,以确保它获得准确的范围样本。根据这篇文章:
对于第一个桶,下边界是生成直方图的列的最小值。
但是,它没有提到最后一个桶/最大值。
随着8日上午的抽样统计更新,该样本错过了表中的最高值(7日)。
由于我们对前一天的数据进行了大量查询,这会导致基数估计不准确和许多查询超时。
SQL Server 不应该识别该键的最高值并将其用作最大值RANGE_HI_KEY吗?或者这只是不使用更新的限制之一FULLSCAN?
版本 SQL Server 2012 SP2-CU7。我们目前无法升级,因为OPENQUERYSP3中的行为改变了SQL Server 和 Oracle 之间的链接服务器查询中的数字四舍五入。
从MSDN:
如果
(SAMPLE, FULLSCAN, RESAMPLE)未指定任何示例选项,查询优化器默认对数据进行采样并计算样本大小。
如何确定统计的默认样本量?
我浏览了 MSDN,但没有找到任何公式或方法来确定默认样本大小。到处都只有公式来触发自动统计更新。任何指针都会有所帮助。
SQL Server 统计中的直方图步数是如何决定的?
为什么即使我的键列有超过 200 个不同的值,它也被限制为 200 个步骤?有什么决定因素吗?
演示
模式定义
CREATE TABLE histogram_step
(
id INT IDENTITY(1, 1),
name VARCHAR(50),
CONSTRAINT pk_histogram_step PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)
在我的表中插入 100 条记录
INSERT INTO histogram_step
(name)
SELECT TOP 100 name
FROM sys.syscolumns
Run Code Online (Sandbox Code Playgroud)
更新和检查统计信息
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Run Code Online (Sandbox Code Playgroud)
直方图步骤:
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 3 | 1 | 1 | …Run Code Online (Sandbox Code Playgroud) 在 Amazon RDS SQL Server(任何版本/版本)中,创建一个临时表并更新其统计信息。这工作正常:
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t;
GO
CREATE TABLE #t (id INT NOT NULL);
GO
UPDATE STATISTICS #t
GO
Run Code Online (Sandbox Code Playgroud)
但是尝试在统计信息上指定行数:
UPDATE STATISTICS #t
WITH ROWCOUNT = 100000000;
GO
Run Code Online (Sandbox Code Playgroud)
你会得到一个错误:
消息 1088,级别 16,状态 12,第 1 行 找不到对象“#t”,因为它不存在或您没有权限。
STATS_STREAM、ROWCOUNT 和 PAGECOUNT 选项已记录在案,但未得到官方支持。AWS RDS SQL Server 是否有解决方法以便它们工作?