我最近参与维护一组具有一些有趣索引问题的数据库。最让我恼火的是开发、测试、模型和生产机器之间的指标差异。由于差异使得调优查询变得相当困难,因此同步它们是我的第一个项目之一。
当我比较了测试和模型环境时,我注意到模型环境中的大多数索引都STATISTICS_NORECOMPUTE设置为 ,ON而测试中的索引没有。在所有环境中,都有更新所有数据库统计信息的夜间作业。
我以前从未处理过STATISTICS_NORECOMPUTE,所以这里是我的问题。处理此设置时是否有任何最佳做法?如果我在一天结束时进行统计更新,最好打开STATISTICS_NORECOMPUTE所有索引的所有环境?或者有充分的理由不这样做吗?
编辑:我发现了金佰利特里普的关于这一主题的博客之一在这里,似乎表明STATISTICS_NORECOMPUTE应谨慎充其量只能使用。但我仍然担心在全球范围内关闭它。有没有人试过这个,他们经历了什么?
sp_updatestats在生产环境中的 SQL Server上运行是否安全?
或者更确切地说,更新 sql server 上的所有统计信息有什么影响?它可以在运行时“阻塞”sql server 并导致用户超时或其他问题吗?
我试图更好地理解(从概念上)统计、执行计划、存储过程执行之间的关系。
我说统计信息仅在为存储过程创建执行计划时使用,而在实际执行上下文中不使用,我说的对吗?换句话说,如果这是真的,一旦创建了计划(并假设它被正确重用),“最新”统计数据有多重要?
我读过的一篇文章(统计、行估计和升序日期列)特别激励我,该文章描述的场景与我每天面对的几个客户数据库非常相似。
在我们使用特定存储过程定期查询的最大表之一中,我们有一个升序日期/时间列。
当您每天添加十万行时,您如何防止执行计划变得陈旧?
如果我们经常更新统计信息来解决这个问题,在这个存储过程的查询中使用 OPTION (RECOMPILE) 提示是否有意义?
任何意见或建议将不胜感激。
更新:我使用的是 SQL Server 2012 (SP1)。
如果您能深入了解VACUUMPostgreSQL 9.3 中的功能,我将不胜感激。我通读了文档并进行了一些搜索,但找不到明确的答案。
我正在为 9.3 服务器设置每周一次的数据库维护工作。
其中一部分将是一个VACUUM FULL. 这是一个很小的数据库,我有一个不错的周末维护窗口,所以我可以FULL毫无问题地运行它。
ANALYZE在命令中添加选项有什么意义吗?
根据 9.3 文档:
VACUUM FULL将表的全部内容重写到一个没有额外空间的新磁盘文件中,允许将未使用的空间返回给操作系统。
如果表已完全重新创建,那么我是否需要特别要求ANALYZE发生或在将行写入表的新版本时自动更新统计信息?
我有一个在谓词上使用函数的查询,如下所示:
commentType = 'EL'
AND commentDateTime >= DATEADD(month,datediff(month,0,getdate()) - 13,0)
Run Code Online (Sandbox Code Playgroud)
我在 commentType 上有一个过滤索引,它有 40K 行,当我运行查询时,Index Seek 的估计行数非常准确(大约 11K),但对于下一步(排序运算符),它完全忽略了统计信息和只是估计过滤索引中的总行数。
为什么会这样?我知道有关sargability的基础知识,并且我只是为了理智而进行了测试,将 dateadd 替换为实际日期(2014-01-01),瞧......排序开始正确猜测行数......
为什么会发生这种情况,我该如何解决?我不能通过一个固定的日期...
作为更广泛的收购项目的一部分,我刚刚继承了大约 20 个 SQL Server 实例。我正在评估性能,我不喜欢维护计划的实施方式。
我每天都在看到全面的索引重建(我可以处理这个)以及每天手动更新统计数据。
大约一半的数据库已设置为 Auto Update Statistics = False,原因尚不清楚,除了我被告知是为了减少“性能问题”...
我一直认为并致力于将其设置为 True 的最佳实践,并认为如果此设置为 True,则不需要手动更新。我错了吗?
任何人都可以解释将此设置为 False 的好处是什么,而是每天进行手动更新?
我应该提到一些数据库是高度事务性的(每天数百万次插入、删除、更新),其他数据库在事务率方面很低,有些几乎是只读的。虽然没有押韵或理由将自动更新设置设置为 False。好像是彩票。
我从一开始说,我的问题/问题类似于此之前的一个,但因为我不知道的原因或起始信息是一样的,我决定后,我的问题有一些更多的细节。
手头问题:
初步调查:
有罪查询:
Select qt.query_sql_text,
q.query_id,
qt.query_text_id,
rs1.runtime_stats_id AS runtime_stats_id_1,
interval_1 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi1.start_time),
p1.plan_id AS plan_1,
rs1.avg_duration AS avg_duration_1,
rs2.avg_duration AS avg_duration_2,
p2.plan_id AS plan_2,
interval_2 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi2.start_time),
rs2.runtime_stats_id AS runtime_stats_id_2
From sys.query_store_query_text AS qt
Inner Join sys.query_store_query AS …Run Code Online (Sandbox Code Playgroud) SQL Server 有一种叫做“多列统计”的东西,但这并不是人们认为的意思。
我们来看看下面的示例表:
CREATE TABLE BadStatistics
(
IsArchived BIT NOT NULL,
Id INT NOT NULL IDENTITY PRIMARY KEY,
Mystery VARCHAR(200) NOT NULL
);
CREATE NONCLUSTERED INDEX BadIndex
ON BadStatistics (IsArchived, Mystery);
Run Code Online (Sandbox Code Playgroud)
这样,我们就在我们拥有的两个索引上创建了两个统计信息:
BadIndex 的统计数据:
+--------------+----------------+-------------------------+
| All density | Average Length | Columns |
+--------------+----------------+-------------------------+
| 0.5 | 1 | IsArchived |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 37 | IsArchived, Mystery |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 41 | IsArchived, Mystery, Id |
+--------------+----------------+-------------------------+
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS …Run Code Online (Sandbox Code Playgroud) 我在 S2 版本 (50 DTU) 下运行 Azure SQL 数据库。正常使用服务器通常会挂在10%左右的DTU。但是,此服务器会定期进入一种状态,它将在数小时内将数据库的 DTU 使用率发送到 85-90%。然后突然间它恢复到正常的 10% 使用率。
在这种过载状态下,应用程序对服务器的查询似乎仍在快速运行。
我可以从 S2 => 任何东西(例如 S3) => S2 扩展服务器,它似乎清除了它挂在的任何状态。但是几个小时后它会再次重复相同的过载状态循环。我注意到的另一件奇怪的事情是,如果我在 S3 计划 (100 DTU) 24/7 上运行此服务器,我没有观察到这种行为。只有当我将数据库缩小到 S2 计划 (50 DTU) 时才会出现这种情况。在 S3 计划中,我始终保持 5-10% 的 DTU 使用率。显然没有得到充分利用。
我已经检查了 Azure SQL 查询报告以查找恶意查询,但我并没有真正看到任何异常,它显示我的查询使用资源,正如我所期望的那样。
正如我们在这里看到的,使用量都来自数据 IO。如果我在此处更改性能报告以显示 MAX 的顶级数据 IO 查询,我们会看到:
查看这些长期运行的查询似乎指向统计更新。并不是真正从我的应用程序运行的任何东西。例如,查询 16302 显示:
SELECT StatMan([SC0], [SC1], [SC2], [SB0000]) FROM (SELECT TOP 100 PERCENT [SC0], [SC1], [SC2], step_direction([SC0]) over (order by NULL) AS [SB0000] FROM (SELECT [UserId] AS [SC0], [OrganizationId] AS …Run Code Online (Sandbox Code Playgroud) 我偶然发现了 SQL Azure 中的一个问题,其中Sort-operator 由于行估计不佳而溢出到 TempDB 中。
TenantId-column 对每个租户的表进行分区FILTER PREDICATE上述所有查询添加一个TenantIdIndex Seeks检索由于租户之间的行数差异很大,基数估计器产生的估计值非常低。这与两个内部连接相结合,进一步减少了估计,使得实际产生 3600 行的查询预计只产生 3。这是 3 个数量级的下降。
Filtered Statistics为那些产生大量行的键值定义,作为对 CE 的额外提示。OPTION ( RECOMPILE )适用于某些谓词,但不适用于TenantId通过上述安全策略注入的谓词。INNER JOINs更改为s 可以LEFT OUTER JOIN改善错误连接估计,但由于我们使用实体框架,我更喜欢不需要更改查询的解决方案。注意:显然,如果唯一的方法是重写查询,那么这就是我们将要走的路线。我欢迎您的任何想法,谢谢!
排序运算符用于分页。我实际上不想检索所有行。所以简而言之,排序需要发生在数据库中(而不是在应用程序中)。
另外,要明确的是,这里的问题不是 EF 生成的查询。这是一个简单的查询,带有许多INNER/ …
sql-server statistics azure-sql-database cardinality-estimates