例如考虑 SQL 查询:
SELECT
A.[Name],
ROW_NUMBER() OVER(ORDER BY A.[Name] ASC)
FROM
[FooTable] AS A
Run Code Online (Sandbox Code Playgroud)
在这里,我观察到按 A.[Name] 排序的返回结果。如果我将 ROW_NUMBER 函数中定义的排序列更改为另一列,那么结果将再次按该列排序。
我希望将行号分配给行,但我不希望这些行按照相同的标准进行排序。这仅仅是查询执行方式的副作用(在我的情况下是在 SQL Server 2008 R2 上)还是这种行为是否有保证?(我找不到这样的保证的参考)。
在对慢查询进行调查期间,执行计划似乎异常次优(嵌套循环执行了 900 万次执行搜索,其中估计执行次数为 1)。在确认了一些确实过时的相关统计数据后,我重建了统计数据并且性能问题得到了有效解决。
此数据库启用了自动更新统计信息(默认情况下启用)。我知道有一个基于 20% + 500 行修改(更新/插入/删除)的自动统计更新阈值。多个索引似乎已在很大程度上超过了此阈值,因此似乎存在 (A) 自动更新问题或 (B) 更新策略比我在网上找到的更多文档。
我很欣赏可以设置计划任务来更新统计信息,如果找不到其他解决方案,这可能是我们采取的方法,但它确实让我们感到困惑,为什么如此大量的修改不会触发某些统计数据的自动更新 - 了解为什么可能会帮助我们决定哪些统计数据需要由计划任务更新。
一些补充说明:
在负载测试创建数据的数据库中注意到了该问题,因此在短时间内添加了大量数据,因此如果自动更新定期发生(例如,最多一天一次)那么这可以解释一些观察到的行为。此外,我们的负载测试往往会给数据库带来很大的压力,因此我想知道 SQL 是否在负载很重时推迟了统计信息更新(随后由于某种原因不更新统计信息)。
在尝试使用包含连续 INSERT、SELECT 和 DELETE 语句的测试脚本重新创建此问题时,问题并未发生。我想知道这里的区别是否是这些语句每个都会影响每个 SQL 语句的许多行,而我们的负载测试脚本倾向于单独插入行。
有问题的数据库设置为“简单”恢复模式。
一些相关链接:
我也通过微软连接提出了这个问题:
更新 2011-06-30:
在进一步调查中,我相信超出阈值级别(例如 500 行 + 20%)的统计数据是问题查询未使用的统计数据,因此它们可能会在查询运行时更新这需要他们。对于该统计数据是通过查询中使用,这些被定期更新。剩下的问题是,仅在相对较少的插入之后,这些统计数据就会严重误导查询计划优化器(例如,在估计数量为 1 的情况下导致上述 900 万次左右的搜索)。
我此时的预感是问题与主键选择不当有关,键是使用 NEWID() 创建的唯一标识符,因此这会很快创建高度碎片化的索引 - 特别是作为 SQL 中的默认填充因子服务器是 100%。我的预感是,在相对较少的行插入后,这会以某种方式导致误导性统计数据 - 低于重新计算统计数据的阈值。这可能都不是问题,因为我已经生成了大量数据而没有中途重建索引,因此糟糕的统计数据可能是由此产生的非常高的索引碎片的结果。我想我需要将 SQL Server 维护周期添加到我的负载测试中,以便更好地了解真实系统长时间内的性能。
更新 2012-01-10:
另一个需要考虑的因素。SQL Server 2005 中添加了两个跟踪标志(并且似乎在 2008 年仍然存在)以解决与出现过时和/或误导性统计数据相关的特定缺陷。有问题的标志是:
DBCC TRACEON(2389)
DBCC TRACEON(2390)
Run Code Online (Sandbox Code Playgroud)
MSDN:Ian Jose 的 WebLog:升序键和自动快速更正统计 数据,Fabiano Amorim
在决定启用这些标志时,您当然应该非常小心,因为它们可能会产生不利影响。
我刚刚遇到了 SQL 的一部分,它的行为与我预期的不同(请参阅下面的有关 SQL 的提炼版本,该版本演示了问题模式)。
(这是在 SQL Server 2008 R2 SP2 64 位上)
“在这里做一些工作”部分会引发错误并触发 CATCH 块中的错误处理。错误编号为 515(尝试将空值插入不可为空的列),因此 RAISERROR 报告错误,但随后循环继续,再次尝试工作,在无限循环中引发错误等。
我希望 RAISERROR 导致执行退出循环。这里发生了什么?
谢谢
WHILE (@Applied <> 1)
BEGIN
BEGIN TRY
-- === Do some work here ===
-- Successfully applied
SET @Applied = 1;
END TRY
BEGIN CATCH
-- Save the error details
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
-- Test for a deadlock or uncommittable transaction
IF (@ErrorNumber = 1205 OR @ErrorNumber …
Run Code Online (Sandbox Code Playgroud)