小编Joh*_*ner的帖子

显示估计的执行计划会生成 CXPACKET、PAGELATCH_SH 和 LATCH_EX [ACCESS_METHODS_DATASET_PARENT] 等待

我在4个vCPU VM运行Microsoft SQL Server 2016 SP2-CU6(13.0.5292.0)与max degree of parallelism设置为2cost threshold for parallelism设置为50

早上,当我尝试显示SELECT TOP 100查询的估计执行计划时,我遇到了大量等待,并且呈现估计计划的操作需要几分钟,通常在 5 到 7 分钟的范围内。同样,这不是查询的实际执行,这只是显示Estimated Execution Plan 的过程

sp_WhoIsActive将显示PAGEIOLATCH_SH等待或LATCH_EX [ACCESS_METHODS_DATASET_PARENT]等待,当我在操作期间运行Paul Randal 的 WaitingTasks.sql脚本时,它显示CXPACKET等待,工作线程显示PAGEIOLATCH_SH等待:

在此处输入图片说明

*资源描述字段= exchangeEvent id=Port5f6069e600 WaitType=e_waitPortOpen waiterType=Coordinator nodeId=1 tid=0 ownerActivity=notYetOpened waiterActivity=waitForAllOwnersToOpen

工作线程看起来将整个stats表带入内存(因为这些页码以及从 Paul Randal 的查询点显示的后续页码指向stats表的聚集键)。一旦计划确实回来了,即使在我看到stats缓存中的大部分表损耗,只剩下各种记录(我认为由于类似查询的搜索操作而被拉出)之后,它在当天剩余时间内基本上是即时的。

如果查询实际上是使用使用 SCAN 运算符的计划执行的,我会期望这种初始行为,但是为什么在评估执行计划时这样做只是为了到达上面链接的计划中所示的 SEEK 运算符?我可以做些什么(除了在办公时间之前运行此语句以便适当缓存我的数据)来帮助提高性能?我假设一对覆盖索引将是有益的,但它们真的能保证行为的任何变化吗?我必须在此处处理一些存储和维护窗口限制,并且查询本身是从供应商解决方案生成的,因此此时欢迎任何其他建议(除了更好的索引)。

performance sql-server sql-server-2016

13
推荐指数
2
解决办法
820
查看次数

为什么并行(重新分区流)运算符会将行估计减少到 1?

我正在使用 SQL Server 2012 企业版。我遇到了一个 SQL 计划,它表现出一些我认为并不完全直观的行为。在执行大量并行索引扫描操作后,会发生并行(重新分区流)操作,但它会终止索引扫描 (Object10.Index2) 返回的行估计值,将估计值减少到 1。我已经进行了一些搜索,但是没有遇到任何可以解释这种行为的东西。查询非常简单,尽管每个表都包含数百万的记录。这是 DWH 加载过程的一部分,这个中间数据集在整个过程中被触及了几次,但我的问题特别与行估计有关。有人可以解释为什么在并行(重新分区流)运算符中准确的行估计值变为 1?还,

我已将完整计划发布到Paste the Plan

这是有问题的操作:

在此处输入图片说明

包括计划树,以防添加更多上下文:

在此处输入图片说明

我能运行到的一些变化这个连接项目由保罗·怀特(进一步深入explination在自己的博客提交这里)?至少这是我发现的唯一一个似乎与我遇到的情况非常接近的东西,即使没有 TOP 运算符在起作用。

sql-server execution-plan sql-server-2012 cardinality-estimates

12
推荐指数
2
解决办法
7149
查看次数

使用加窗函数优化子查询

由于我的性能调优技巧似乎永远不够用,我总是想知道我是否可以针对某些查询执行更多优化。此问题涉及的情况是嵌套在子查询中的 Windowed MAX 函数。

我正在挖掘的数据是对不同组较大集的一系列事务。我有 4 个重要的字段,交易的唯一 ID,一批交易的组 ID,以及与各自唯一交易或交易组相关的日期。大多数情况下,集团日期与批次的最大唯一交易日期相匹配,但有时会通过我们的系统进行手动调整,并在捕获集团交易日期后进行唯一日期操作。此手动编辑不会按设计调整组日期。

我在此查询中确定的是唯一日期落在组日期之后的那些记录。以下示例查询构建了与我的场景大致相当的内容,SELECT 语句返回我正在查找的记录,但是,我是否以最有效的方式接近此解决方案?这需要一段时间才能在我的事实表加载期间运行,因为我的记录计数在前 9 位数字中,但主要是我对子查询的蔑视让我想知道这里是否有更好的方法。我并不关心任何索引,因为我相信它们已经到位;我正在寻找的是一种替代查询方法,它可以实现相同的目标,但效率更高。欢迎任何反馈。

CREATE TABLE #Example
(
    UniqueID INT IDENTITY(1,1)
  , GroupID INT
  , GroupDate DATETIME
  , UniqueDate DATETIME
)

CREATE CLUSTERED INDEX [CX_1] ON [#Example]
(
    [UniqueID] ASC
)


SET NOCOUNT ON

--Populate some test data
DECLARE @i INT = 0, @j INT = 5, @UniqueDate DATETIME, @GroupDate DATETIME

WHILE @i < 10000
BEGIN

    IF((@i + @j)%173 = 0)
    BEGIN
        SET @UniqueDate = GETDATE()+@i+5
    END
    ELSE
    BEGIN …
Run Code Online (Sandbox Code Playgroud)

performance sql-server sql-server-2012 window-functions query-performance

9
推荐指数
3
解决办法
5835
查看次数

只读副本上的长时间运行查询,在主副本上需要一些时间

我有一个 4 节点 AG 设置,如下所示:

所有节点的VM硬件配置:

  • Microsoft SQL Server 2017 企业版 (RTM-CU14) (KB4484710)
  • 16 个 vCPU
  • 356 GB RAM(这个故事很长……)
  • 最大并行度:1(根据应用程序供应商的要求)
  • 并行性的成本阈值:50
  • 最大服务器内存 (MB):338944 (331 GB)

AG配置:

  • 节点 1:主节点或同步提交非可读辅助节点,配置为自动故障转移
  • 节点 2:主节点或同步提交非可读辅助节点,配置为自动故障转移
  • 节点 3:具有异步提交的可读辅助集,配置为手动故障转移
  • 节点 4:具有异步提交的可读辅助集,配置为手动故障转移

有问题的查询:

这个查询没有什么特别疯狂的地方,它提供了应用程序内各个队列中未完成工作项的摘要。您可以从下面的执行计划链接之一中查看代码。

主节点上的执行行为:

在 Primary 节点上执行时,执行时间一般在 1 秒左右。这是执行计划,以下是从主节点的 STATISTICS IO 和 STATISTICS TIME 捕获的统计信息:

(347 rows affected)
Table 'Worktable'. Scan count 647, logical reads 2491, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table …
Run Code Online (Sandbox Code Playgroud)

performance sql-server availability-groups sql-server-2017 query-performance

9
推荐指数
3
解决办法
1433
查看次数

CMS 服务器列表中区分大小写的排序

我必须相信这是有原因的,但对于我的生活,我无法弄清楚。看起来任何中央管理服务器中服务器名称的排序都是区分大小写的,而不管充当 CMS 的服务器本身的排序规则如何。

附件是我的本地机器上托管的 CMS 示例,它配置了 SQL_Latin1_General_CP1_CI_AS 的服务器排序规则。CI 意思是不区分大小写。从包含 CMS 对象的系统表中进行选择时,将返回正确的顺序,但是正如您在此屏幕截图中所见,服务器在 UI 中的列出方式,顺序显然是以区分大小写的方式处理的。

在此处输入图片说明

由于它似乎与服务器级别无关,因此我假设它与客户端工具相关,但在工具中没有任何地方可以识别会影响此的排序规则级别(甚至区分大小写设置)。

显然,这个问题没有什么重要的,但是如果有人确实知道如何强制用户界面不区分大小写,我会很感激,因为我喜欢将我的服务器名称命名为 Camel Case,这会影响排序。

sql-server central-management-server case-sensitive

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

使用 FOR SYSTEM_TIME 子句时历史表的查询/表提示

可能是一个非常简单的问题,但是FOR SYSTEM_TIME在查询时态表时使用语句时,有没有办法为历史表指定查询/表提示?我怀疑不是,但我想在放弃这个之前仔细检查一下。

这是一个dbfiddle,它显示了我所知道的为查询指定提示的不同方式的基本细分,我能弄清楚如何传递与历史表交互的查询和/或表提示的唯一方法是转换查询到UNION ALLlive 和 history 表之间,而不是使用FOR SYSTEM_TIME子句。

在使用该FOR SYSTEM_TIME子句时尝试指定历史表提示时,出现以下错误:

Msg 308 Level 16 State 1 Line X
Index '<<HISTORY TABLE INDEX NAME>>' on table '<<LIVE TABLE NAME>>' (specified in the FROM clause) does not exist.
Run Code Online (Sandbox Code Playgroud)

在使用该FOR SYSTEM_TIME子句时尝试指定指向历史记录表的查询提示时,出现以下错误:

Msg 8723 Level 16 State 1 Line X
Cannot execute query. Object '<<HISTORY TABLE>>' is specified in the TABLE HINT clause, but is not used in the query or does …
Run Code Online (Sandbox Code Playgroud)

sql-server query hints temporal-tables

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

将表用作没有 sp_getapplock/sp_releaseapplock 的队列

我有一个需要执行的命令列表,所有这些命令都包含在我命名为 的表中myQueue。这个表有点独特,因为一些命令应该组合在一起,以便它们的执行按顺序执行,而不是并发执行,因为同时执行它们会导致不需要的数据工件和错误。因此,队列不能以典型的FIFO / LIFO方式分类,因为出队顺序是在运行时确定的。

总结一下:

  1. 命名的表myQueue将充当命令队列(其中出队顺序在运行时确定)
  2. 命令以随机方式添加到表中
  3. 命令可以归入,如果是,则必须由单个工作线程以有序、顺序的方式执行
  4. 当命令出列时,可以运行任意数量的工作线程
  5. 出列是通过 aUPDATE而不是 a执行的,DELETE因为此表用于所述命令的历史性能报告

我目前的方法是通过sp_getapplock/sp_releaseapplock调用使用显式互斥逻辑来迭代这个表。虽然这按预期工作,但该方法会生成足够的锁定,因此在任何给定时间都无法在队列上迭代大量工作线程。在阅读了 Remus Rusanu关于该主题优秀博客文章后,我决定尝试使用表格提示,希望可以进一步优化我的方法。

我将包含下面的测试代码,但总结一下我的结果,使用表提示和消除对sp_getapplock/ 的调用的缺点sp_releaseapplock最多会导致以下三种不良行为:

  1. 死锁
  2. 多个线程执行包含在单个组中的命令
  3. 命令中缺少线程分配

不过,从积极的方面来说,当代码适应死锁时(例如,重试当前包含的违规操作),不使用sp_getapplock/sp_releaseapplock且不会表现出不良行为的方法 2 和 3 的执行速度至少是两倍,如果不是更快的话.

我希望有人会指出我没有正确构建出列语句,这样我仍然可以继续使用表提示。 如果那不起作用,那就这样吧,但我想看看它是否可以做到同样的事情。

可以使用以下代码设置测试。

myQueue表的创建和人口与命令类似于够我的工作量:

CREATE TABLE myQueue
(
    ID INT  IDENTITY (1,1) PRIMARY KEY CLUSTERED,
    Main    INT, …
Run Code Online (Sandbox Code Playgroud)

sql-server concurrency locking queue

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

Seek 谓词中的标量运算符和 1 的行估计

我试图了解我在查询计划中看到的一些相当大且不守规矩的行为。特别是,我正在查看在其谓词中包含标量操作的聚集索引查找操作。我怀疑标量操作只是其中一个表的别名(如Seek Predicate中的标量运算符中所述),因为两列的类型相同,并且此操作馈入并行嵌套循环(左外连接)运算符。

不过,我的问题更多是关于 1 的行估计,而不是更接近实际行数(约 670 万)的数字。标量操作是否会扼杀优化器正确估计行的能力?我假设是这样,也假设这会损害我的查询执行计划的最佳状态,但我不确定。有人可以证实或反驳我的怀疑以及为什么吗?

这是有问题的操作:

在此处输入图片说明

版本:SQL Server 2012 企业版

sql-server execution-plan sql-server-2012

5
推荐指数
1
解决办法
712
查看次数

如何在从查询缓存或查询存储中提取的执行计划中包含“实际行”计数?

显然,在调整时看到实际的执行计划很重要,通常我通过启用查询计划输出SET STATISTICS XML ON并运行任何需要一些 TLC 的查询,但是我如何才能看到计划的历史运行或进程的实际记录计数我不能轻松手动运行(或在测试环境中模拟)?

当我通过显示sys.dm_exec_query_plansys.dm_exec_text_query_plan仅显示估计的行数从查询缓存中提取此信息时。使用查询存储 DMV 时存在相同的行为,sys.query_store_plan. 由于所有这些 DMV 都在提取已使用的实际计划,我希望在计划的图形表示中看到实际的行执行计数,但它们并不存在。

sys.dm_exec_query_statsDMV返回的信息只是在某种程度上有用,因为它返回语句的总计数,但计划中的详细操作员计数似乎隐藏在历史计划中。在 2014 年,我们sys.dm_exec_query_profiles使用了DMV,这有助于当前正在执行的计划,但这在查看历史执行时也无济于事。

这些信息是否存储在其他地方?我是否应该将估计行数视为实际计数(我对此表示怀疑,但因为我在问......)?是否有请求此功能的连接项目我可以投票?

sql-server execution-plan dmv

5
推荐指数
1
解决办法
416
查看次数

间隙和岛屿 - 寻找最近的岛屿

我正在处理以下场景,其中我的时间数据属于island 和 gaps。每隔一段时间,我需要根据事件发生的时间将落入现有间隙内的事件与其最近的岛屿相关联。

为了演示,假设我有以下定义我的时间段的数据:

在此处输入图片说明

这个数据是除了哪个ID之间存在间隙连续的27,对于所述时间段2017-07-26 00:03:00通过2017-07-26 00:07:00

为了确定最近的岛屿,我目前将差距分为两个时期,如下所示:

在此处输入图片说明

如果我有一个属于这个差距的事件,GapWindowStart/End时间将决定我需要将事件与哪个岛相关联。因此,例如,如果我有一个发生在 的事件2017-07-26 00:03:20,我会将该事件与 ID 相关联,2相反,如果我有一个事件发生在 ,2017-07-26 00:05:35我会将该事件与 ID 相关联7

最有效的方法,我已经能够编写我的方法,迄今为止,是组装使用的空白伊茨克奔甘的从SQL Server MVP深海潜水书第3解决方案通过ROW_NUMBER窗口函数,然后每一个分裂的差距CROSS APPLY作用的语句就像一个简单的UNPIVOT操作。

这是我用来组装最近的岛屿集的方法的db<>fiddle计划。

确定最近的岛屿后,我使用事件的事件时间来确定与所述事件相关联的最近岛屿。因为这些岛屿全天都在变化,所以我无法制作静态主表,而是必须在遇到事件时在运行时构建所有内容。

这是一个db<>fiddle 计划,显示应该针对随机事件时间使用什么 NearestIsland 值。

对于通常会落入间隙的给定事件,是否有更好的方法来找出最近的岛屿?例如,是否有更有效的方法来识别间隙或更有效的方法来识别最近的岛屿?我什至以最好的逻辑方式来解决这个问题吗?这个问题没有什么重要的,但我总是试图弄清楚是否有一种“更好”的方法来解决问题,我认为这个问题有助于一些创造力,所以我很想看到其他高性能的选择。

我目前使用的环境是 SQL 2012,但我们很快就会迁移到 SQL 2016 环境,所以我几乎可以接受任何东西。

第二个 db<>fiddle 链接的代码如下:

-- Creation of Test Data
CREATE TABLE #tmp
( …
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2012 gaps-and-islands sql-server-2016

5
推荐指数
1
解决办法
818
查看次数