我有一个包含大约 2 亿条记录的事务表,一个主键聚集在 Id 上,还有 2 个索引:
在继续实际查询以更新统计信息之前,我运行这两条语句
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))我会立即得到结果。 …
我正在查看执行计划并从右到左阅读它。
例子:
1<-2<-3<-4
^
|_5
Run Code Online (Sandbox Code Playgroud)
所以4和5是并行执行的。当两者都完全完成时,则 3 完全执行,然后 2 完全运行,然后 1。
这是正确的还是可能存在以下情况:
3 甚至在 4 和 5 完全完成之前就开始执行。
2 甚至在 3 完全完成之前就开始执行。
我想按Estimated Operator Cost对执行计划 XML 进行排序,但问题是:
\nSQL Server 执行计划在 UI 中具有“估计操作员成本”条目:
\n\n...但是 XML 输出中缺少该值。
\n关于如何对 XML 进行排序有多种建议,例如:
\n但两者都与我所拥有的相差甚远,因为“估计运营商成本”似乎是一个超级复杂的计算。
\n请问这个问题有什么解决办法吗?
\n我有一个疑问:
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 亿行的惰性假脱机操作,但如果不执行,则不会执行。
我正在从使用对象 ID 和属性类型作为聚集索引的属性表迁移一些存储“键值”样式的数据(我也尝试过作为非聚集索引):
\nCREATE 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);\nRun 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\'\nRun Code Online (Sandbox Code Playgroud)\n通过对该临时表进行 14 个联接,查询将在几秒钟内完成。如果有 15 个连接,查询需要一分钟,如果有 16 个以上连接,则半小时后仍在运行。
\n我已经检查了所有联接是否存在意外条件,这会导致返回太多行,当它在 1 分钟内返回时,它只返回正确的行,所以我不认为存在意外的笛卡尔联接。设置 MAXDOP 值不会影响它,并且查询运行一分钟时返回的查询计划不会标记任何问题。
\n对于 SQL,我错过了什么,导致它在聚集索引上进行大量联接,理论上应该很快,而且记录数量如此之少?
\n我无法获得实际执行计划,因为查询未完成,并且因为它使用临时表,所以我无法获得其估计计划。我尝试将临时表捏造为数据库中的真实表并生成估计计划,但 2 分钟后该计划仍未生成,因此看起来延迟是在“创建计划”方面
\n粘贴查询的缩短版本的计划:brentozar.com/pastetheplan/ ?id=Hy76dd92i
\n我已经更新了数据库的统计数据以防万一,但它仍然没有生成计划。
\n我过去处理过越来越多有问题的连接查询,其中计划编译仍然是即时的。我觉得它在“生成计划”步骤失败这一事实一定意味着什么。
\n不幸的是,更新到最新的 CU 没有帮助。 …
在 SQL Server 中,我们可以使用它set statistics profile on来启用会话分析。然后您可以执行任何一条语句,相应的执行计划将以表格形式显示。是否可以将这种流行的表单计划保存到某个表中,以便我可以对其进行过滤?
我有一个视图,其中涉及 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 出现在执行计划中。
我在我的数据库中记录了最慢的查询,其中一个让我感到惊讶,在列表中显示了很多次,并且执行通常需要很多秒。
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 没有更改。
我错过了什么?
我们已经在生产中遇到了几次问题,它看起来像一个存储过程获得了一个新的、糟糕的计划并开始造成严重破坏。不幸的是,在执行 dbcc freeproccache 之前,我们无法捕获之前和之后的计划以查看不良计划的情况,我们也没有设置查询存储。
我的问题是,什么会导致 sql server 为存储过程生成新计划?特别是对于一直运行的 sp。我知道的一些是:
需要一些帮助来理解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
execution-plan ×10
sql-server ×10
index ×1
optimization ×1
table-spool ×1
top ×1
update ×1
view ×1