这篇文章我想谈下SQL Server里一个非常重要的性能调优话题:重编译(Recompilations) 。当你执行非常简单的存储过程(使用临时表)时,就会发生。今天我想奠定SQL Server里重编译的基础,它们为什么会发生,下篇文章我会向你展示通过不同方式重写你的存储过程避免重编译。

什么是重编译?

在我谈SQL Server里重编译细节前,首先来看看下面一个很简单存储过程。

 CREATE PROCEDURE DemonstrateTempTableRecompiles
AS
BEGIN
CREATE TABLE #TempTable
(
ID INT IDENTITY(1, 1) PRIMARY KEY,
FirstName CHAR(4000),
LastName CHAR(4000)
) INSERT INTO #TempTable (FirstName, LastName)
SELECT TOP 1000 name, name FROM master.dbo.syscolumns SELECT * FROM #TempTable DROP TABLE #TempTable
END
GO

从代码里可以看出,这个存储过程并没有什么特殊。第1步我们创建临时表,然后临时表里会插入一些记录,最后用简单的SELECT语句获取插入的数据。在SQL Server里,像这样的代码你可能谢了上百次,甚至上千次。

接下来我们用SQL Server Profiler跟踪下重编译事件。点击【工具】->【SQL Server Profiler】。输入登录密码后,会弹出【跟踪属性】窗口。点击【事件选择】,勾选【显示所有事件】,然后在事件列表里勾选【Stored Procedures】下列事件:

  • SP:Starting
  • SP:StmtStarting
  • SP:Recompile
  • SP:Completed

点击【运行】开始跟踪。在我们创建存储过程后,我们运行存储过程。

 EXEC DemonstrateTempTableRecompiles

从上图可以看到,我们在执行存储过程时,发生了2次重编译。

重编译意味这SQL Server在运行执行计划时,对执行计划进行了重编译。这会带来额外的CPU开销,最后减少服务器工作的吞吐量。但现在的问题是,为什么这些重编译会发生?
SQL Server执行重编译主要是在下列2种情况发生:

  • 架构改变(Scheme Shanges)
  • 统计信息更新(Statistic Updates)

在刚才执行的存储过程里,因为这2个情况我们触发了重编译。我们再来看下刚才的存储过程,第1步我们建立了临时表,当我们在TempDb里建立临时表时,你就改变了你的数据库架构,因为这个原因第1个重编译发生了。

在临时表创建后,你插入了一些记录。因此SQL Server需要去更新临时表聚集索引的统计信息——聚集索引是由SQL Server通过主键(PRIMARY KEY)创建。1个简单的存储过程就引起了SQL Server里2个重编译。哇噢~~~~~

小结

重编译会给临时表带来巨大的性能负荷。另一方面,临时表有准确的统计信息帮助查询优化器生成更好性能的执行计划。因此,当你处理大量数据时,使用临时表才是正确选择。对于小量数据,重编译引起的CPU负荷,比通过统计信息获得性能提升的CPU负荷会高很多。

下篇文章,我会为你介绍表变量(Table Variables),我们会看到使用表变量如何避免重编译的副作用——还有它们带来的其它性能问题。请继续关注!

附:SQL Server 2014的童鞋可以使用下列脚本通过扩展事件(Extended Event)跟踪重编译事件。

 CREATE EVENT SESSION [TrackRecompiles] ON SERVER
ADD EVENT sqlserver.sql_statement_recompile
(
ACTION
(
sqlserver.plan_handle,
sqlserver.sql_text
)
)
ADD TARGET package0.event_file(SET filename = N'c:\temp\TrackRecompiles.xel')
WITH
(
MAX_MEMORY = 4096 KB,
EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 30 SECONDS,
MAX_EVENT_SIZE = 0 KB,
MEMORY_PARTITION_MODE = NONE,
TRACK_CAUSALITY = OFF,
STARTUP_STATE = OFF
)
GO -- Start the Event Session
ALTER EVENT SESSION TrackRecompiles
ON SERVER
STATE = START
GO

参考文章:

https://www.sqlpassion.at/archive/2014/11/10/recompilations-part-1/

探秘重编译(Recompilations)(1/2)的更多相关文章

  1. 探秘重编译(Recompilations)(2/2)

    在上一篇文章里,我讨论了使用临时表如何引起SQL Server里的重编译.在文章最后我提到,今天这篇文章我会聚焦表变量(Table Variables)的更多信息,它可以避免重编译的昂贵开销.我们来详 ...

  2. SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨

    SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile).那么引发存储过程重编译的条件有哪一些呢 ...

  3. sqlserver 存储过程中使用临时表到底会不会导致重编译

    曾经在网络上看到过一种说法,SqlServer的存储过程中使用临时表,会导致重编译,以至于执行计划无法重用, 运行时候会导致重编译的这么一个说法,自己私底下去做测试的时候,根据profile的跟踪结果 ...

  4. [译]SQL Server 之 查询计划缓存和重编译

    查询优化是一个复杂而且耗时的操作,所以SQL Server需要重用现有的查询计划.查询计划的缓存和重用在多数情况下是有益的的,但是在某些特殊的情况下,重编译一个查询计划可能能够改善性能. SELECT ...

  5. DXperience重编译汉化的方法

    1. 必须有DXperience相应版本的全部源代码SourceCode.把全部源代码复制到\Program Files\Developer Express .NET vX.X\Sources目录.目 ...

  6. SQL 编译与重编译

    编译的含义 当SQLSERVER收到任何一个指令,包括查询(query).批处理(batch).存储过程.触发器(trigger) .预编译指令(prepared statement)和动态SQL语句 ...

  7. 关于T-SQL重编译那点事,WITH RECOMPILE和OPTION(RECOMPILE)区别仅仅是存储过程级重编译和SQL语句级重编译吗

    本文出处:http://www.cnblogs.com/wy123/p/6262800.html   在考虑重编译T-SQL(或者存储过程)的时候,有两种方式可以实现强制重编译(前提是忽略导致重编译的 ...

  8. 关于T-SQL重编译那点事,内联函数和表值函数在编译生成执行计划的区别

    本文出处:http://www.cnblogs.com/wy123/p/6266724.html 最近在学习 WITH RECOMPILE和OPTION(RECOMPILE)在重编译上的区别的时候,无 ...

  9. SQL Server 执行计划重编译的两大情况

    1.与正确性相关的重编译 1.为表或视图添加列,删除列. 2.为表添加约束.默认值.规则,删除约束.默认值.规则. 3.为表或视图添加索引. 4.如果计划用不用索引而这个索引被删除. 5.删除表中的统 ...

随机推荐

  1. solr详解,开发必备

    1.基础知识 创建索引的过程如下: (1).建立索引器IndexWriter,这相当于一本书的框架 (2).建立文档对象Document,这相当于一篇文章 (3).建立信息字段对象Field,这相当于 ...

  2. 如何实现LBS轨迹回放功能?含多平台实现代码

    本篇文章告诉您,如何实现轨迹回放.并且提供了web端,iOS端,Android端3个平台的轨迹回放代码.拷贝后可以直接使用.另外,文末有小彩蛋,算是开发者的福利. Web端/JavaScript 实现 ...

  3. Unity3D Shader入门指南(一)

    动机 自己使用Unity3D也有一段时间了,但是很多时候是流于表面,更多地是把这个引擎简单地用作脚本控制,而对更深入一些的层次几乎没有了解.虽然说Unity引擎设计的初衷就是创建简单的不需要开发者操心 ...

  4. 启动和JQuery绑定--AngularJS学习笔记(二)

    上一篇简单的分析了AngularJS的项目结构,后面就开始分析具体的源代码了. 从angularFiles.js中的定义可以看出有几个文件直接位于src根目录,并不是隶属于某个模块.这几 个分别是mi ...

  5. Activity intent经常使用的 FLAG

    Intent.FLAG_ACTIVITY_NEW_TASK 默认的跳转类型,会重新创建一个新的Activity,不过与这种情况,比方说Task1中有A,B,C三个Activity,此时在C中启动D的话 ...

  6. Azure SoftEther VPN

    装个vs2015,想装全组建还得爬墙… 曾经的 Azure OpenVPN 项目 (http://azure-openvpn.github.io/) 好几年木有更新 改用 SoftEther VPN ...

  7. 获取枚举类型的描述description

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...

  8. 一致性哈希算法(consistent hashing)【转】

    一致性哈希算法 来自:http://blog.csdn.net/cywosp/article/details/23397179       一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希 ...

  9. python + hadoop (案例)

    python如何链接hadoop,并且使用hadoop的资源,这篇文章介绍了一个简单的案例! 一.python的map/reduce代码 首先认为大家已经对haoop已经有了很多的了解,那么需要建立m ...

  10. saiku缓存整理

    使用saiku的人,肯定都有这么一个经历,查询了一次多维分析数据表,第二次之后就特别快,因为它缓存了结果,可问题是过了一天,甚至几天,来源数据早都更换了,可还是这个缓存结果.问题来了,缓存不失效! 那 ...