我在我们的生产 sql 服务器上遇到了一个问题,其中临时表对象需要很长时间才能删除(当使用小型同步删除时很明显)。我无法在其他 sql 服务器上重现这一点(同样指定使用相同数量的主轴来提供 tempdb 数据文件(拆分为相同数量的文件(每个物理核心 1 个))。在 SQL 2005 Enterprise (SP2 - 3042) 上。
更新:还有一个因素——看起来最有可能。该服务器上有 >500 个数据库。另一个大于 800 的服务器也运行这些 drop 很慢。那是我唯一拥有很多数据库的其他服务器。
第二次更新:重启有问题的服务器将允许立即执行 create 和 drop 语句。在接下来的几个小时内(在应用程序运行时),测试的性能会下降,直到达到(看起来是)平台期。我有一项在后台运行的工作,每 30 分钟测试一次。我会看看几天后的结果,看看执行时间是否相同。我认为他们会。
第三次更新:虽然没有一个正在执行的语句显示闩锁等待 CPU 资源,但使用 sp_whoisactive 我看到在 delta_interval = 30(秒)运行期间,运行查询 CPU_delta 报告大约 30,000(毫秒?),当我在执行期间观察 perf 时在执行期间似乎有一个核心的 CPU 峰值。这些在 16 个 cpu 盒上,因此当其他流量发生时通过 perfmon 看到可能有点困难,但它似乎在执行 drop 语句期间增加了 cpu 的价值。
在我测试过的大多数服务器上,创建和销毁 20 个具有唯一名称(一列,无行)的小型临时表的时间不到 20 毫秒。在一台服务器上需要> 5 秒。绝大多数 (>95%) 的时间都花在 drop 语句上。
在执行期间,没有显式等待,也没有报告阻塞,并且 perfmon 不显示 I/O 子系统上的任何数据或日志文件负载。
我查看了高峰和低使用时间,当大量表标记为销毁和低时。操作需要 5 秒左右来处理 20 个 drop …
我在 SQL 2012 SP1 (ent) 上有一个并行查询,它在用户定义的资源调控器池中运行的速度比在用户定义的池中运行的慢得多(2 秒与 125 到 140 秒在用户定义的池中 = ~ 75 倍慢)比在其中运行的相同查询默认资源池。
两次执行之间的查询计划哈希是相同的,并且统计 io 为所有操作返回相同的值。我已经确认执行计划没有额外的溢出警告(两者都有一个),并且查询的内存授予是相同的。
用户定义的池工作负载组
<QueryPlan DegreeOfParallelism="4" MemoryGrant="2384096" CachedPlanSize="384" CompileTime="3608" CompileCPU="2712" CompileMemory="15672">
<ThreadStat Branches="5" UsedThreads="20">
<ThreadReservation NodeId="0" ReservedThreads="20" />
</ThreadStat>
<MemoryGrantInfo SerialRequiredMemory="5632" SerialDesiredMemory="2360768" RequiredMemory="28960" DesiredMemory="2384096" RequestedMemory="2384096" GrantWaitTime="0" GrantedMemory="2384096" MaxUsedMemory="93872" />
<OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="209715" EstimatedPagesCached="104857" EstimatedAvailableDegreeOfParallelism="4" />
Run Code Online (Sandbox Code Playgroud)
默认池
<QueryPlan DegreeOfParallelism="4" MemoryGrant="2384096" CachedPlanSize="384" CompileTime="3016" CompileCPU="2660" CompileMemory="15672">
<ThreadStat Branches="5" UsedThreads="20">
<ThreadReservation NodeId="0" ReservedThreads="20" />
</ThreadStat>
<MemoryGrantInfo SerialRequiredMemory="5632" SerialDesiredMemory="2360768" RequiredMemory="28960" DesiredMemory="2384096" RequestedMemory="2384096" GrantWaitTime="0" GrantedMemory="2384096" MaxUsedMemory="88768" />
<OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="209715" EstimatedPagesCached="104857" EstimatedAvailableDegreeOfParallelism="4" /> …
Run Code Online (Sandbox Code Playgroud) 这是在 SQL 2005 SP2 上,但我怀疑这通常适用于所有查询提示。
我有一个临时的 sql 语句,它仅仅因为 OPTION(重新编译)而获得不同的查询计划。批处理语句永远不会(实际上)被重用,因为它使用非参数化动态 sql 生成,其中语句随日期/其他参数而变化。我已经通过检查缓存的 plan_handle 确认了这种情况,在批量更改时总是使用不同的 ID。
当我执行 dbcc freeproccache 时,我希望我为语句获得的查询计划与添加了“选项(重新编译)”查询提示的查询计划完全相同。但它不是,它实际上完全不同(要快得多)。
有谁知道为什么添加查询提示会导致引擎选择不同的查询计划?
声明是这样的
dbcc freeproccache
go
sp_executesql '
declare @begindate datetime
declare @enddate datetime
select @begindate='1/1/2011'
select @enddate='2/1/2011'
select count(*) from tableA where tableA.datecolumn between @begindate and @enddate
and exists(
select A
union all select B
union all select C
)'
Run Code Online (Sandbox Code Playgroud)
我所要做的就是更改语句以使用重新编译查询提示,然后我会得到不同的(更好的)查询计划。
dbcc freeproccache
go
sp_executesql '
declare @begindate datetime
declare @enddate datetime
select @begindate='1/1/2011'
select @enddate='2/1/2011'
select count(*) from tableA where tableA.datecolumn …
Run Code Online (Sandbox Code Playgroud)