标签: execution-plan

如何调查 Sql Server 选择“错误”索引的原因?

我有一个包含大约 2 亿条记录的事务表,一个主键聚集在 Id 上,还有 2 个索引:

  • IX_SiloId_ChangedTime_IncludeTime
  • IX_SiloId_Time_IncludeContent

在继续实际查询以更新统计信息之前,我运行这两条语句

Update STATISTICS dbo.[Transaction] IX_SiloId_ChangedTime_IncludeTime WITH FULLSCAN
Update STATISTICS dbo.[Transaction] IX_SiloId_Time_IncludeContent WITH FULLSCAN
Run Code Online (Sandbox Code Playgroud)

这是我的查询:

DECLARE @Query SiloTimeQueryTableType -- (SiloId, Time) with primary key clustered on SiloId
INSERT INTO @Query VALUES 
(1, '2020-12-31'), -- 1000 total values, though it's still the same problem with just one

SELECT  t.*
FROM    [Transaction] t
INNER JOIN @Query q
    ON t.SiloId = q.SiloId
WHERE 
    t.Time >= q.Time

Run Code Online (Sandbox Code Playgroud)

现在发生的情况是 Sql Server 选择的原因IX_SiloId_ChangedTime_IncludeTime。然后就需要永远。如果我使用,WITH (INDEX(IX_SiloId_Time_IncludeContent))我会立即得到结果。 …

index sql-server execution-plan

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

在下一次执行开始之前,执行计划的每个成员是否都完整运行?

我正在查看执行计划并从右到左阅读它。

例子:

1<-2<-3<-4
      ^
      |_5
Run Code Online (Sandbox Code Playgroud)

所以4和5是并行执行的。当两者都完全完成时,则 3 完全执行,然后 2 完全运行,然后 1。

这是正确的还是可能存在以下情况:

  1. 3 甚至在 4 和 5 完全完成之前就开始执行。

  2. 2 甚至在 3 完全完成之前就开始执行。

sql-server execution-plan sql-server-2019

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

按估计的操作员成本对执行计划 XML 进行排序

我想按Estimated Operator Cost对执行计划 XML 进行排序,但问题是:

\n

SQL Server 执行计划在 UI 中具有“估计操作员成本”条目:

\n

在此输入图像描述

\n

...但是 XML 输出中缺少该值。

\n

关于如何对 XML 进行排序有多种建议,例如:

\n\n

但两者都与我所拥有的相差甚远,因为“估计运营商成本”似乎是一个超级复杂的计算

\n

请问这个问题有什么解决办法吗?

\n

sql-server execution-plan

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

添加“前 20 个”会大大减慢查询速度!

我有一个疑问:

select * from Aview where field=20
order by id desc
Run Code Online (Sandbox Code Playgroud)

这将在大约 1 秒内从视图中返回 2700 行。

在查询中添加“top 20”使 MSSQL 在 43 秒内返回!

这是一个很难重现的问题,重建统计数据可以修复该问题几天,但随后又回来了。

我使用 SQL 已经有几十年了,我从未见过添加“top”导致时间增加的情况。

查看执行计划,如果执行前 20 条,它似乎正在执行 9.6 亿行的惰性假脱机操作,但如果不执行,则不会执行。

sql-server execution-plan sql-server-2016 top table-spool

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

大量“键值”连接会导致 SQL Server 查询速度呈指数级减慢

我正在从使用对象 ID 和属性类型作为聚集索引的属性表迁移一些存储“键值”样式的数据(我也尝试过作为非聚集索引):

\n
CREATE TABLE [dbo].[#attrs](\n    [DataMigrationEventObjectID] [int] NOT NULL,\n    [AttributeType] [varchar](128) NOT NULL,\n    [AttributeValue] [varchar](255) NULL\n) \nCREATE CLUSTERED INDEX pk ON #attrs ([DataMigrationEventObjectID],AttributeType);\n
Run Code Online (Sandbox Code Playgroud)\n

我添加了属性值来选择值,因为数据库中的属性表有很多其他数据,我可以仅为此迁移事件选择它。使用我的测试数据集来填充此表的查询会插入约 3k 行,并且运行时间不到一秒(我的数据集中总共约有 50 个对象,每个对象都有多个属性)。

\n

查询中表的连接如下所示,连接聚集索引:

\n
        INNER JOIN #attrs obj_gvn\n        ON obj_gvn.DataMigrationEventObjectID = obj.DataMigrationEventObjectID\n        AND obj_gvn.AttributeType = \'GivenName\'\n
Run Code Online (Sandbox Code Playgroud)\n

通过对该临时表进行 14 个联接,查询将在几秒钟内完成。如果有 15 个连接,查询需要一分钟,如果有 16 个以上连接,则半小时后仍在运行。

\n

我已经检查了所有联接是否存在意外条件,这会导致返回太多行,当它在 1 分钟内返回时,它只返回正确的行,所以我不认为存在意外的笛卡尔联接。设置 MAXDOP 值不会影响它,并且查询运行一分钟时返回的查询计划不会标记任何问题。

\n

对于 SQL,我错过了什么,导致它在聚集索引上进行大量联接,理论上应该很快,而且记录数量如此之少?

\n
\n

我无法获得实际执行计划,因为查询未完成,并且因为它使用临时表,所以我无法获得其估计计划。我尝试将临时表捏造为数据库中的真实表并生成估计计划,但 2 分钟后该计划仍未生成,因此看起来延迟是在“创建计划”方面

\n

粘贴查询的缩短版本的计划:brentozar.com/pastetheplan/ ?id=Hy76dd92i

\n

我已经更新了数据库的统计数据以防万一,但它仍然没有生成计划。

\n

我过去处理过越来越多有问题的连接查询,其中计划编译仍然是即时的。我觉得它在“生成计划”步骤失败这一事实一定意味着什么。

\n

不幸的是,更新到最新的 CU 没有帮助。 …

sql-server optimization execution-plan sql-server-2019

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

是否可以将统计结果保存到表格中?

在 SQL Server 中,我们可以使用它set statistics profile on来启用会话分析。然后您可以执行任何一条语句,相应的执行计划将以表格形式显示。是否可以将这种流行的表单计划保存到某个表中,以便我可以对其进行过滤?

此平板电脑表单执行计划的示例如下所示: 在此输入图像描述

sql-server execution-plan

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

有多少 LEFT JOINS 使 VIEW 无法使用?

我有一个视图,其中涉及 20 多个表上的 LEFT JOINS 到基表,但是在查询此视图并查看执行计划时,我得到了完全出乎意料的结果。

例如,对于下面的查询,我希望在表上进行聚集索引查找:

SELECT id FROM dbo.TableName WHERE id = 256
Run Code Online (Sandbox Code Playgroud)

而当我使用视图时,我会在表上找到聚集索引以及 3 个嵌套循环(左外连接)。

SELECT id FROM dbo.ViewName WHERE id = 256
Run Code Online (Sandbox Code Playgroud)

为什么会出现这种情况?上面是一个非常简单的例子,但是当从视图中选择额外的列时,越来越多的不必要的 LEFT JOINS 出现在执行计划中。

sql-server execution-plan sql-server-2008-r2 view

0
推荐指数
1
解决办法
321
查看次数

只更新一列,奇怪的执行计划

我在我的数据库中记录了最慢的查询,其中一个让我感到惊讶,在列表中显示了很多次,并且执行通常需要很多秒。

UPDATE books SET last_read='2018-12-31 11:23:45' WHERE book_id='15'
Run Code Online (Sandbox Code Playgroud)

book_id 是 int 身份 PK(集群),last_read 是日期时间。查询是用单引号中的 15 编写的,因此需要转换,但我无法想象这是一个大问题,因为每个查询只进行一次转换。表上有 6 个索引,但列 last_read 未涉及或包含在其中任何一个中。PK 在 book_id 上,没什么特别的。

估计的执行计划告诉我:

UPDATE: 0%
Clustered Index Update (on the PK constraint): 100%
Run Code Online (Sandbox Code Playgroud)

我不希望查询更新任何索引,因为 last_read 没有以任何方式编入索引,并且 book_id 没有更改。

我错过了什么?

sql-server execution-plan sql-server-2016

0
推荐指数
1
解决办法
274
查看次数

什么导致sql server为存储过程生成新计划?

我们已经在生产中遇到了几次问题,它看起来像一个存储过程获得了一个新的、糟糕的计划并开始造成严重破坏。不幸的是,在执行 dbcc freeproccache 之前,我们无法捕获之前和之后的计划以查看不良计划的情况,我们也没有设置查询存储。

我的问题是,什么会导致 sql server 为存储过程生成新计划?特别是对于一直运行的 sp。我知道的一些是:

  • dbcc freeproccache
  • 重新启动服务器
  • 选项重新编译

sql-server execution-plan sql-server-2016

0
推荐指数
1
解决办法
137
查看次数

使用哈希流不同运算符进行查询调整更新

需要一些帮助来理解UPDATE以下语句之一的缓慢:-

UPDATE TOP (100) xyz
SET xyz.flag = 1
OUTPUT inserted.Rcode, inserted.EDR, inserted.id, abc.EID,abc.CID,abc.ENID,abc.Cdate
FROM dbo.table1 xyz WITH (UPDLOCK, READPAST)
INNER JOIN dbo.table2 abc WITH (NOLOCK)
on xyz.id=abc.id
WHERE xyz.flag = 0
Run Code Online (Sandbox Code Playgroud)

表1有大约。50 万行,表 2 大约有。500 万行

慢计划

哈希匹配不同流运算符显示黄色警报,消息为:

操作员使用 Tempdb 溢出数据,以溢出级别 4 和 1 个溢出线程执行”

构建残差:

database.dbo.table2.id as abc.id = database.dbo.table2.id as abc.id

我截了屏。不幸的是,由于安全原因,我不能提供更多,甚至不能提供匿名计划。从我的工作站我无法访问互联网,所以我无法让计划浏览器在那里运行。

在此处输入图片说明

通常,对于较小的行子集,它在几秒钟内,就像我们刚刚匹配 10K 行或其他东西一样。但是随着数据量的增加,这似乎是一个临界点,应用程序无法承受 1 分钟的运行时间。从 SSMS 我得到 30 秒,但从应用程序我们有平均。约 50 秒 RCSI 处于测试阶段。

我的好计划没有显示 Hash Match Flow Distinct 运算符,如我的屏幕截图所示,而其余计划保持不变。好的一个在 3 秒左右完成。正如所见,该操作员花费了近 16 秒。我们可以通过适当的索引或查询重写来消除它吗? …

sql-server execution-plan update sql-server-2014 query-performance

0
推荐指数
1
解决办法
162
查看次数