小编cro*_*sek的帖子

如何改进行估计以减少溢出到 tempdb 的机会

我注意到,当 tempdb 事件溢出(导致查询缓慢)时,对于特定连接,行估计通常会偏离。我已经看到溢出事件发生在合并和散列连接中,它们通常将运行时间增加 3 到 10 倍。这个问题涉及如何在减少溢出事件机会的假设下改进行估计。

实际行数 40k。

对于此查询,计划显示错误的行估计(11.3 行):

select Value
  from Oav.ValueArray
 where ObjectId = (select convert(bigint, Value) NodeId
                     from Oav.ValueArray
                    where PropertyId = 3331  
                      and ObjectId = 3540233
                      and Sequence = 2)
   and PropertyId = 2840
option (recompile);
Run Code Online (Sandbox Code Playgroud)

对于此查询,计划显示了良好的行估计(56k 行):

declare @a bigint = (select convert(bigint, Value) NodeId
                       from Oav.ValueArray
                      where PropertyId = 3331
                        and ObjectId = 3540233
                        and Sequence = 2);

select Value
  from Oav.ValueArray
 where ObjectId = @a               
   and PropertyId = 2840
option (recompile); …
Run Code Online (Sandbox Code Playgroud)

join sql-server optimization

11
推荐指数
2
解决办法
1万
查看次数

使用 try/catch 进行动态 SQL 备份命令时如何记录错误详细信息

在使用 try catch 和动态 sql 的存储过程中发出备份命令时,与直接运行备份命令相比,错误消息非常普遍。

在 SP 中尝试/捕获:

    begin try
        execute sp_executesql @sql;  -- a backup command
    end try
    begin catch  
        print ERROR_MESSAGE();  -- save to log, etc.
    end catch
Run Code Online (Sandbox Code Playgroud)

结果是

50000:usp_Backup:117: BACKUP DATABASE 异常终止。

whearea 发出原始命令:

    backup DATABASE someDb to disk...
Run Code Online (Sandbox Code Playgroud)

结果更好的细节:

查找错误 - SQL Server 数据库错误:文件“H:\FolderName\Filename.bak:”112(磁盘空间不足。)发生不可恢复的 I/O 错误。

有没有办法将这些细节捕获到存储过程中的变量中(记录,传回调用者,重试逻辑)?似乎细节正在通过消息通道传递,但我希望它们在 SP 中可用。

sql-server backup error-handling

10
推荐指数
1
解决办法
2万
查看次数

对并行标量 UDF 的支持是一个合理的功能请求吗?

标量 UDF 强制执行整体串行计划,这是有据可查的。

并行运行函数

给定大量行进入管道中必须计算 UDF 的点,为什么引擎不能将它们分配给处理器?如果 UDF 中没有状态,那么顺序应该无关紧要。

有人声称 UDF 是一个必须使用光标的黑匣子。我可以看到,对于在迭代之间维护某些状态但似乎应该可以并行化的情况,用户游标无法在 SP 中并行化。

解释为什么引擎强制整个计划是串行的,而不仅仅是 UDF 计算阶段的额外要点。

对并行 UDF 的支持是一个合理的要求吗?

sql-server parallelism functions

10
推荐指数
2
解决办法
2600
查看次数

如何在数据库重启后清除错误 15404(除了重启)

每隔一段时间(例如~几个月),SQL Server 代理每小时作业将开始报告错误 15404 并继续这样做直到被干预。

[298] SQLServer 错误:15404,无法获取有关 Windows NT 组/用户“DOMAIN_NAME\SomeDomainAccount”的信息,错误代码 0x6e。[SQLSTATE 42000] (ConnIsLoginSysAdmin)

有时,在手动重新启动 SQL Server 引擎和 SQL Server 代理服务后会立即发生第一次失败。可以通过重新启动机器来清除问题。

作业所有者是错误消息中列出的名称,并且是 SQL Server 管理员。

SQL Server 引擎服务帐户看起来是一个服务帐户(我相信它是默认安装帐户(比通用 NetworkService 好一个档次,以防止引擎/代理实例之间的干扰):

   NT Service\MSSQL$INSTNAME
Run Code Online (Sandbox Code Playgroud)

如果作业总是失败,那将是一回事,但由于作业在重新启动后成功,这让我认为像这样的服务帐户应该可以正常工作,并且存在一些 A/D 计时问题或可能存在错误。当 IT 被问及 A/D 配置时,回答通常是“没有任何变化”。

  • 重新启动引擎和代理服务可能会导致作业开始失败。
  • 机器重新启动即可解决问题。
  • 随后立即重新启动引擎和代理不再导致作业失败。

链接: 如何解决 SQL Server 8198 错误

sql-server sql-server-agent jobs active-directory

9
推荐指数
1
解决办法
2万
查看次数

如何针对索引改进受 DateAdd() 约束的视图中 1 行的估计

使用 Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64)。

给定一个表和索引:

create table [User].[Session] 
(
  SessionId int identity(1, 1) not null primary key
  CreatedUtc datetime2(7) not null default sysutcdatetime())
)

create nonclustered index [IX_User_Session_CreatedUtc]
on [User].[Session]([CreatedUtc]) include (SessionId)
Run Code Online (Sandbox Code Playgroud)

以下每个查询的实际行数为 310 万,估计行数显示为注释。

当这些查询在 View 中提供另一个查询,由于 1 行估计,优化器选择循环连接。 如何在此基础级别改进估计以避免覆盖父查询连接提示或求助于 SP?

使用硬编码日期效果很好:

 select distinct SessionId from [User].Session -- 2.9M (great)
  where CreatedUtc > '04/08/2015'  -- but hardcoded
Run Code Online (Sandbox Code Playgroud)

这些等效查询与视图兼容,但都估计为 1 行:

select distinct SessionId from [User].Session -- 1
 where CreatedUtc …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization view sql-server-2012

9
推荐指数
2
解决办法
372
查看次数

是否可以为不同/分组获得基于搜索的并行计划?

这个问题的一个例子表明,SQL Server 将选择全索引扫描来解决这样的查询:

select distinct [typeName] from [types]
Run Code Online (Sandbox Code Playgroud)

其中 [typeName] 有一个非聚集的、非唯一的升序索引。他的示例有 200M 行,但只有 76 个唯一值。在这种密度下,搜索计划似乎是更好的选择(约 76 次二进制搜索)?

他的情况可以正常化,但问题的原因是我真的想解决这样的问题:

select TransactionId, max(CreatedUtc) 
from TxLog 
group by TransactionId
Run Code Online (Sandbox Code Playgroud)

上有一个索引(TransactionId, MaxCreatedUtc)

使用标准化源 (dt) 重写不会改变计划。

select dt.TransactionId, MaxCreatedUtc
 from [Transaction] dt -- distinct transactions
 cross apply
   (
        select Max(CreatedUtc) as MaxCreatedUtc 
          from TxLog tl
         where tl.TransactionId = dt.TransactionId         
   ) ca
Run Code Online (Sandbox Code Playgroud)

仅将 CA 子查询作为标量 UDF 运行确实显示了 1 次搜索的计划。

select max(CreatedUtc) as MaxCreatedUtc
 from Pub.TransactionLog 
 where TransactionID = @TxId;
Run Code Online (Sandbox Code Playgroud)

在原始查询中使用该标量 UDF 似乎可行,但会失去并行性(UDF 的已知问题): …

index sql-server optimization group-by distinct

8
推荐指数
1
解决办法
415
查看次数

哪些情况可以从 Reduce、Replicate 和 Redistribute 连接提示中受益?

SQL Server 2008 开始的From 子句文档简要提到了 3 个连接提示及其基本机制:

  • 降低
  • 复制
  • 重新分配

然而,似乎没有太多关于何时可能需要使用它们的信息。

似乎它们可以与散列、循环和合并结合使用,这些已经被理解为这个问题的目的。

文档中的相关部分:

对于 SQL 数据仓库和并行数据仓库,这些联接提示适用于两个分布不兼容的列上的 INNER 联接。它们可以通过限制查询处理期间发生的数据移动量来提高查询性能。SQL 数据仓库和并行数据仓库的允许连接提示如下:

  • REDUCE
    减少要为联接右侧的表移动的行数,以使两个分布不兼容的表兼容。REDUCE 提示也称为半连接提示。

  • REPLICATE
    将连接左侧表的连接列中的值复制到所有节点。右侧的表连接到这些列的复制版本。

  • REDISTRIBUTE
    强制将两个数据源分布在 JOIN 子句中指定的列上。对于分布式表,Parallel Data Warehouse 会执行shuffle move。对于复制表,并行数据仓库将执行修剪移动。要了解这些移动类型,请参阅并行数据仓库产品文档中“了解查询计划”主题中的“DMS 查询计划操作”部分。当查询计划使用广播移动来解决分发不兼容的连接时,此提示可以提高性能。

join sql-server hints sql-server-pdw azure-sql-data-warehouse

8
推荐指数
1
解决办法
364
查看次数

如何让交叉应用在视图上逐行操作?

我们有一个针对单项查询优化的视图(200 毫秒无并行性):

select * 
    from OptimizedForSingleObjectIdView e2i
   where ObjectId = 3374700
Run Code Online (Sandbox Code Playgroud)

它也适用于一小组静态 ID(~5)。

select * 
    from OptimizedForSingleObjectIdView e2i
   where ObjectId in (3374700, 3374710, 3374720, 3374730, 3374740);
Run Code Online (Sandbox Code Playgroud)

但是,如果对象来自外部源,那么它会生成一个缓慢的计划。执行计划显示视图部分的执行分支忽略了 ObjectId 上的谓词,而在原始情况下,它使用它们来执行索引查找。

select v.*
  from 
     (
       select top 1 ObjectId from Objects
        where ObjectId % 10 = 0
        order by ObjectId
     ) o  
  join OptimizedForSingleObjectIdView v -- (also tried inner loop join)
    on v.ObjectId = o.ObjectId;
Run Code Online (Sandbox Code Playgroud)

我们不希望投资于“双重”优化非奇异情况的视图。相反,我们“寻求”的解决方案是对每个对象重复调用一次视图,而无需求助于 SP

大多数情况下,以下解决方案会逐行调用视图。但是这次不是,甚至不是只有 1 个对象:

select v.*
  from
     (
       select top 1 ObjectId 
         from Objects …
Run Code Online (Sandbox Code Playgroud)

sql-server execution-plan view cross-apply

7
推荐指数
1
解决办法
1021
查看次数

如何使用合并提示隔离 SQL Server 中的复杂查询

我可以理解,如果我加入“单独快速”的单个查询,组合可能会变慢,因为默认执行计划可能不是最佳的。但是,当我知道一个查询的行数非常少时,我想我应该能够使用提示来控制连接。

select cj.a, cv.b
  from (select distinct a from complexJoin) cj -- 2 rows
 inner loop join complexView cv
    on cj.a = cv.a
 order by cj.a, cv.b
Run Code Online (Sandbox Code Playgroud)

如果 cj <1s 和 cv <1s 期望这是 <~2s 但使用任何提示(合并/散列/循环)通常> 1分钟。

我还尝试使用 CROSS APPLY,因为文档声称内部选择对于每个外部行只执行一次。该查询比手动运行两次内部查询需要大约 100 倍的时间,所以也许我不理解文档。

select cj.a, cv.b
  from (select distinct a from complexJoin) cj -- 2 rows
 cross apply (select * from complexView 
               where a = cj.a) cv
 order by cj.a, cv.b
Run Code Online (Sandbox Code Playgroud)

如果我用“cj”的结果填充临时表,然后加入 _with_no_hint_ 或使用交叉应用,它会很快,但我真的必须求助于它吗?如果我使用临时表并尝试“任何”连接提示(循环/合并/散列),它会很慢,所以这可能是一个关键点。

我不相信深入查询计划的深度(两者都是复杂的开始)是解决一般问题所必需的:我只想保证隔离而不诉诸临时表 - 这真的不可能?

join sql-server optimization hints merge

6
推荐指数
1
解决办法
1010
查看次数

为什么会忽略额外的过滤统计信息(EAV 模式)?

我正在尝试改进此子查询(较大查询的)的行估计。估计显示 1266 行。实际是 117k 行。这个特定的属性(EAV 模式)只定义了两个值(2 和 3):

declare @pPropVal smallint = 2;

select Value, ObjectId 
  from Oav.ValueArray PropName
 where PropName.PropertyId = 897
   and PropName.Value  = @pPropVal
option (recompile)
Run Code Online (Sandbox Code Playgroud)

查询计划按预期显示对 PropertyId 和 Value 索引 IX_ValueArray_PropValObj 的正确搜索谓词。

( A ) 作为改进行估计的尝试,添加了一个额外的统计数据,使行估计略微增加到 3041:

create statistics [ST_SomePropertyName] ON [Oav].[ValueArray](PropertyId, Value, ObjectId)
 where 
     (     
             PropertyId = 897 
         and [Value] is not null
     )
  with fullscan
Run Code Online (Sandbox Code Playgroud)

直方图显示单行。HI 键只是 PropertyId(第一列),根据我的理解,它不是那么有用,它使用的是密度信息。

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS  DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
897             0           196026   0                    1

All density Average Length  Columns
1 …
Run Code Online (Sandbox Code Playgroud)

sql-server statistics eav cardinality-estimates

6
推荐指数
1
解决办法
440
查看次数