运行包含实际执行计划的查询时,根运算符 ( SELECT) 告诉我缓存计划大小为 32KB。
该连接的查询sys.dm_exec_cached_plans和sys.dm_os_memory_objects,看问题的计划,称该值pages_in_bytes和max_pages_in_bytes为32768(32KB),它匹配缓存计划的大小。
我不明白的是 中的值sys.dm_exec_cached_plans.size_in_bytes,即 49152 (48KB) 代表什么。我已经阅读了所有这些专栏的 BOL,特别是size_in_bytes其中说:
"缓存对象消耗的字节数。 "
我无法解决最后一点难题,无法理解它的真正含义。
我知道所有操作符(不是谈论用于排序和散列的额外内存授予)都需要一定数量的固定内存,以存储状态、进行计算等,这些内存与缓存中的优化计划一起存储,但在哪里?
所以,我的问题是:
size_in_bytes意思我知道它们是具有不同功能的不同 DMV,但它们是相关的。在编译(缓存)计划sys.dm_exec_cached_plans加入sys.dm_os_memory_objects在memory_object_address列。我在这里发布问题的原因是我在寻求帮助,了解如何解释 DMV 及其专栏。
如果size_in_bytes是缓存计划大小,为什么SQL Server在实际执行计划中说另一个值?
新查询,新号码:
sys.dm_exec_cached_plans.size_in_bytes 24KBsys.dm_os_memory_objects.pages_in_bytes, .max_pages_in_bytes 16KB。另请注意,此查询不需要为排序和散列操作分配任何额外的内存。
Microsoft SQL Server 2012 - 11.0.5343.0 (X64)
我遇到了开发人员代码,其中 SqlCommand.Prepare() (参见 MSDN)方法在执行 SQL 查询之前被广泛使用。我想知道这样做有什么好处?
样本:
command.Prepare();
command.ExecuteNonQuery();
//...
command.Parameters[0].Value = 20;
command.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)
我玩了一点并进行了追踪。调用Prepare()方法后执行Command,使Sql Server执行如下语句:
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@id int,@desc text',N'INSERT INTO dbo.testtable (id) VALUES (@id)',@id=20'
select @p1
Run Code Online (Sandbox Code Playgroud)
之后,当 Parameter 获取它的值并被SqlCommand.ExecuteNonQuery()调用时,将在 Sql-Server 上执行以下操作:
exec sp_execute 1,@id=20
Run Code Online (Sandbox Code Playgroud)
对我来说,这看起来就像语句在Prepare()执行时被编译。我想知道这样做有什么好处?这是否意味着它被放入计划缓存中,并且可以在使用所需参数值执行最终查询后立即重新使用?
我发现(并在另一个问题中记录了它)使用 SqlParameters 执行的 SqlCommands 总是包含在sp_executesql过程调用中。这使得 Sql Server 能够独立于参数值存储和重用计划。
关于这一点,我想知道该prepare()方法是无用的还是过时的,或者我在这里遗漏了什么?
sql-server execution-plan sql-server-2008-r2 prepared-statement plan-cache
存储过程的缓存中缺少计划的原因是什么?
WITH RECOMPILE我最近在 2 台服务器(SQL Server 2008 R2 和 SQL Server 2012)上工作,它们在缓存中没有计划用于非常消耗资源的存储过程。存储过程中的许多(也许是全部)语句在缓存中也没有计划。一些存储过程非常频繁地执行,例如每秒执行几次。
没有任何内存压力。其中一台服务器的硬件远远超过所需。
我认为丢失的计划是由于在存储过程中间创建了临时表,但这似乎是来自 SQL Server 2000 或更早版本的旧信息。从 SQL Server 2005 开始,重新编译发生在 DDL 之后的语句的语句级别。在所有情况下都是如此还是在较新的版本上仍然会发生?
还有什么可能是导致计划缺失的罪魁祸首?我已经浏览了一些关于这个主题的文章,但似乎没有什么合适的。
在我本周查看的服务器上启用了针对临时工作负载的优化。其中一个存储过程每天只执行一次。我确实有那个代码。我没有每分钟执行超过 100 次的代码,但我可以得到它。我将无法发布代码,但我可以根据我的问题来描述它。
我不相信有人会释放过程缓存或丢弃干净的缓冲区。该客户使用 Solarwinds DPA 作为其监控工具之一。DPA 确实捕获了每天调用一次的存储过程中语句的执行计划之一。由于 non-sargableWHERE子句,该语句有大量读取。如果 DPA 捕获了该语句,则它是一个估计计划,并且曾经在计划缓存中。只是在我们进行故障排除时不在那里。我会让他们开始记录sp_WhoIsActive到一个表。
我正在使用sp_BlitzCache. (我为 Brent Ozar Unlimited 工作)这将显示整个存储过程的计划以及单个语句的计划(如果存在)。如果它们不存在,它会发出警告“我们找不到此查询的计划。可能的原因包括动态 SQL、RECOMPILE提示和加密代码。” 该警告也出现在声明中。
TF 2371 没有到位。我正在查看等待统计数据。服务器很无聊。PLE 超过 130,000。
我现在有 2 个存储过程的代码。其中之一是使用动态 SQLexec (@sql)以便我们知道为什么没有计划。但另一个,也就是每分钟运行超过 100 次的那个,没有任何异常。唯一突出的是临时表是在 1000 多行代码的中间创建的。它也调用了一堆子存储过程。
我一直在 sql 错误日志上发现奇怪的错误消息:
Bocss:每小时都会发生同样的僵局——需要调查
根据以下示例,其他 SPID 的错误日志中还列出了许多重新编译:
2015年9月4日14:30:10,spid64,未知,用于SQLHANDLE 0x0200000059631A288882589E0C54B76404CAE1B97E08D3680000000000000000000000000000000000000000 PlanHandle 0x0600040059631A2860A62B654100000001000000000000000000000000000000000000000000000000000000检测到可能无限的重新编译起始偏移1038结束偏移2600的最后一个重新编译原因是2. 2015年9月4日14时三十分十秒,spid150,未知,是为SQLHANDLE 0x02000000EF886F018C4E0B163812B8B20150FE8FC7E6A06A0000000000000000000000000000000000000000 PlanHandle 0x06000400EF886F01901A816E0600000001000000000000000000000000000000000000000000000000000000起始偏移量998检测到的一个可能的无穷的重新编译结束偏移2520。最后重新编译原因是2. 2015年9月4日14:30:09,spid67,未知检测到可能无限的重新编译为SQLHANDLE 0x0200000057C4C632D9052275CFF2B683B80F29501EE91D730000000000000000000000000000000000000000 PlanHandle 0x0600040057C4C63200EAC2BE3000000001000000000000000000000000000000000000000000000000000000起始偏移1064结束偏移2652是2. 2015年9月4日14最后重新编译原因:30:09,spid163,未知,是为SQLHANDLE 0x02000000E7C7BF0E5D70DE55759C7842860272AD474D69AB0000000000000000000000000000000000000000 PlanHandle探测到一个可能无限的重新编译0x06000400E7C7BF0EF0EB68A52C00000001000000000000000000000000000000000000000000000000000000开始偏移量1028结束偏移2580的最后一个重新编译的原因是2。
是什么导致了这种情况?
按照这篇文章的建议 http://www.sqlservercentral.com/Forums/Topic1479420-146-1.aspx
然后作为安全措施禁用全文目录,这没有区别,所以我完全回滚了更改(删除了新对象等)。这也没什么区别,最后似乎唯一阻止它的是重新启动 SQL 实例,这立即解决了问题。
这也解决了我的问题,但是,我仍然要找出造成这种混乱的原因是什么?
根据我对查询如何编译、存储和检索查询计划的有限了解,我了解多语句查询或存储过程将生成它的查询计划,该查询计划将存储在查询计划缓存中,以供查询在未来执行中使用。
我认为这个计划是通过查询哈希从查询计划缓存中检索的,这意味着如果查询被编辑和执行,哈希是不同的,并且会生成一个新计划,因为在查询计划缓存中找不到匹配的哈希。
我的问题是:如果用户执行的语句是多语句查询中的语句之一,它是否可以将缓存中已有的查询计划的相关部分用于多语句查询?我希望答案是否定的,因为哈希值显然不匹配,但是在多语句查询中对每个语句进行哈希处理是否更好,以便用户可以从查询中运行单个语句来使用它们?
我希望有一些我没有考虑到的并发症(我真的很想知道这些),但似乎我们可以在许多查询计划中存储相同的“语句计划”,占用更多空间和更多CPU 和生成时间。
可能只是显示我的无知。
我最近将最大内存从默认(无限制)降低到 20 GB。这会清除计划缓存中最旧的查询吗?
我们有一个最大内存设置为 24GB 的 SQL Server 2016 SP1。
该服务器有大量编译,这些编译中只有 10% 来自 Ad-Hoc 查询。所以新编译的计划应该存储在计划缓存中,但计划缓存的大小没有增加(大约 3.72GB)。
我怀疑存在导致从缓存中删除计划的本地内存压力。计划缓存压力限制为 5GB。(0-4GB 可见目标内存的 75% + 4GB-64GB 可见目标内存的 10% + 可见目标内存的 5%>64GB)。当缓存存储达到压力限制的 75% 时,应从缓存中删除计划。就我而言,5 GB 的 75% 是 3.75 GB。因此,这可能是高编译的原因。
有没有办法测量(性能,扩展事件,...)从缓存中删除计划?所以我可以确定本地内存压力真的是高编译的原因吗?
我可以想到在计划缓存中存储估计计划而不是实际计划的决定背后的许多原因。但我找不到“正确”的答案。
当您仅重新启动 SQL 服务本身时,服务器缓存是否会被擦除(类似于重新启动 SQL 实例/机器时)?
当执行查询时,SQL Server将产生一个查询计划列表,并启发式地选择成本较低的计划。
所选择的计划将存储在计划缓存中,以供后续看到相同查询时使用。
当表的某些属性发生变化或者重建索引时,它会再次产生一个查询计划列表,并启发式地选择一个成本较低的查询计划,并将其存储在计划缓存中。
但是,MSDN 似乎表明估计计划存储在计划缓存中,请参见下面的屏幕截图。那是对的吗?