第11/24周 重编译

今天我想谈下性能调优培训里的重编译(Recompilations )。当你执行一个查询,SQL Server里另一个变动使你执行计划的剩余部分无效,就会发生重编译。在那个情况下SQL Server需要保证你执行计划的准确性,重编译就会被触发。重编译会给你的SQL Server带来额外的CPU开销。

什么是重编译?

首先我想展示下编译和重编译之间的区别。2个星期前,我们讨论了SQL Server里的编译。当查询优化器把提交的查询转化为实际执行计划时,编译就会发生。这就是说编译在查询执行开始就发生。

另一方面,重编译在查询执行期间就会发生。因此SQL为了保证执行计划的准确性就重编译执行计划的剩余部分。如果执行计划里引用的索引在计划执行时被删除了。这就导致不可接受的结果。SQL Server触发重编译有2个类型:

  • 基于正确性的重编译(Correctness-based Recompilations)
  • 基于最优性能的重编译(Optimality-based Recompilations)

我们来详细看下这2类重编译。当计划不再准确,就会发生基于正确性的重编译(Correctness-based Recompilations)。例如你的数据库架构发生改变(新增或删除索引,删除统计信息),或者你的SET选项发生改变。在那个情况下,重编译就是为了保证你计划的准确。

如果你的统计信息发生改变,就会发生基于最优性能的重编译(Optimality-based Recompilations)。统计信息发生改变,一方面是SQL Server会自动更新你的统计信息,另一方面是你触发了统计信息的人为更新。那样的情况可以是书签查找正越过临界点,SQL Server需要引入全表/聚集索引扫描。

我们现在再来详细看一个在查询执行期间,触发很多重编译的常见特殊情景——临时表(Temp Tables)!

临时表(Temp Tables)

是的,你没看错:当你与临时表(Temp Tables)打交道时,在SQL Server里你会引起重编译。我们来一个非常简单的存储过程定义:

 1 CREATE PROCEDURE DoWork
 2 AS
 3 BEGIN
 4    CREATE TABLE #TempTable
 5    (
 6       ID INT IDENTITY(1, 1) PRIMARY KEY,
 7       FirstName CHAR(4000),
 8       LastName CHAR(4000)
 9    )
10    INSERT INTO #TempTable (FirstName, LastName)
11    SELECT TOP 1000 name, name FROM master.dbo.syscolumns
12    SELECT * FROM #TempTable
13 END
14
15 GO

这个存储过程创建了一个简单的临时表,往它里面插入了几条记录,最后从表里获取几条记录。很简单,是不是?关键是这个存储过程在执行期间触发了2个重编译:

  • 第1个触发重编译是因为你创建了一个新的临时表。通过创建临时表你就在改变你的数据库架构。这个触发了基于正确性的重编译(Correctness-based Recompilations)。
  • 当你执行SELECT语句时,你触发了第2个重编译。刚才你在临时表里插入了几条记录,因此SQL Server需要更新你的统计信息。这里你就引入了基于最优性能的重编译(Optimality-based Recompilations)。

如何避免这2个重编译呢?你可以使用表变量(Table Variables)代替临时表。用表变量的话,你就不再改变数据库架构了(它只是个变量),而且表变量是没有统计信息的。这2个重编译就消失了。但是当然,用表变量会引入另一个性能问题:因为它们没有统计信息,SQL Server总是估计它们只有1行,因此你的参数预估就会完全一塌糊涂。

因此表变量在SQL Server里只有特殊使用情景:当你只和小量数据打交道时。当你和大量数据打交道时,你仍应该使用临时表,因为它们会给你准确的统计信息,你也可以在上面建立索引。缺点就是它们会触发重编译。

小结

今天我们讨论了性能调优培训里的重编译(Recompilations)。如你所见,因为SQL Server需要保证你的执行计划的准确性才会有重编译发生。我们还看了重编译经常发生的特殊场景——临时表(Temp Tables)。

这些重编译可以通过使用表变量来解决,但这里你也要意识到带来的副作用。下星期我会谈下SQL Server里的并行执行计划(Parallel Execution Plans),里面会有很多有趣的事情发生。好好享受接下来的7天,到时候见!

时间: 2024-10-13 02:46:47

第11/24周 重编译的相关文章

第10/24周 计划缓存

在这一期的性能调优培训里,我想详细谈下SQL Server里计划缓存及其副作用.在上一周你已经学到,每个提交给SQL Server的逻辑查询会编译成物理执行计划.那个执行计划然后会被缓存,即被称为计划缓存,用作后期的重用.首先我们来看下即席SQL语句(adhoc SQL statements,对应的反义词:prepared SQL statements)的副作用,即带来的性能问题. 即席SQL语句(adhoc SQL statements) 每次当你提交一个即席SQL语句到SQL Server时

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

这篇文章我想谈下SQL Server里一个非常重要的性能调优话题:重编译(Recompilations) .当你执行非常简单的存储过程(使用临时表)时,就会发生.今天我想奠定SQL Server里重编译的基础,它们为什么会发生,下篇文章我会向你展示通过不同方式重写你的存储过程避免重编译. 什么是重编译? 在我谈SQL Server里重编译细节前,首先来看看下面一个很简单存储过程. 1 CREATE PROCEDURE DemonstrateTempTableRecompiles 2 AS 3 B

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

原文:探秘重编译(Recompilations)(2/2) 在上一篇文章里,我讨论了使用临时表如何引起SQL Server里的重编译.在文章最后我提到,今天这篇文章我会聚焦表变量(Table Variables)的更多信息,它可以避免重编译的昂贵开销.我们来详细分析下. 表变量(Table Variables) 表变量总局限于提交到SQL Server的批处理语句范围.当你在批处理语句范围外引用表变量时,SQL Server就会返回你一条错误信息.这是和临时表相比第1个重大区别.下列代码向你展示

DXperience重编译汉化的方法

1. 必须有DXperience相应版本的全部源代码SourceCode.把全部源代码复制到\Program Files\Developer Express .NET vX.X\Sources目录.目标目录的默认位置是在C:\Program Files\Developer Express .NET vX.X\Sources\(其中X.X为应替换相应的版本号,以下不再重复说明).2. 必须创建一个强名称的文件.要创建此文件,必须执行下面的命令建立你自己的密钥:sn -k StrongKey.snk

Hadoop 2.3.0-cdh5.1.0重编译

Hadoop版本有很多,这里我选择的是cdh版本.cdh是Cloudera公司在Apache原版基础经过加工的东西.chd具体的下载地址为: http://archive-primary.cloudera.com/cdh5/cdh/5/ 版本信息如下: Hadoop:Hadoop 2.3.0-cdh5.1.0 JDK:1.7.0_79 Maven:apache-maven-3.2.5(3.3.1以及更高版本必须在JDK1.7以上) Protobuf:protobuf-2.5.0 Ant:1.7.

分析存储过程重编译的起因以及避免

为了改进性能,分析重编译的起因很重要.往往,重编译可能并不需要,可以避免它以改进性能.了解导致重编译发生的不同条件有助于评估重编译的起因,并决定在重编译不必要时避免它的方法. 存储过程重编译在以下情况下发生: 存储过程语句中引用的常规表.临时表或视图的架构变化.架构变化包括表的元数据或表上索引的变化: 常规或临时表的列上的绑定(如默认/规则)变化. 表索引或列上的统计的变化超过一定的阈值. 存储过程编译时一个对象不存在,但是在执行期间创建(延迟对象解析): SET选项变化: 执行计划老化并释放:

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

本文出处:http://www.cnblogs.com/wy123/p/6262800.html   在考虑重编译T-SQL(或者存储过程)的时候,有两种方式可以实现强制重编译(前提是忽略导致重编译的其他因素的情况下,比如重建索引,更新统计信息等等), 一是基于WITH RECOMPILE的存储过程级别重编译,另外一种是基于OPTION(RECOMPILE)的语句级重编译. 之前了解的比较浅,仅仅认为是前者就是编译整个存储过程中的所有的语句,后者是重编译存储过程中的某一个语句,也没有追究到底是不

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

曾经在网络上看到过,SqlServer的存储过程中使用临时表,会导致执行计划无法重用, 运行时候会导致重编译的这么一个说法,自己私底下去做测试的时候,根据profile的跟踪结果, 如果不是统计信息变更导致导致的重编译,单单是使用临时表,并不会导致重编译, 但是对于一些特殊的情况,又确实会出现重编译的, 为了弄清楚这个问题,查阅了大量的资料,才把这个问题弄清楚,这里特意记录下来,希望武断地认为存储过程中使用了临时表就会导致重编译的这个观点得到纠正. 首先进行下面的测试,我们知道,导致临时表重编译

win8.1 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建

win8.1 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建 重编译的好处:可以调试的时候看OpenCV的源代码. 重编译要得到的东西:Debug版本和Release版本的dll,lib,头文件.(dll添加到环境变量里,运行时用,自己编译的dll调试时可以跟踪到Opencv的源码内:lib和头文件配置到编译器里) PS:如果只是使用Opencv而不需要跟踪源码,则使用Opencv自带的库文件即可.跳到5配置Opencv开发环境,对应的文件都在..\opencv\b