MSSQL优化(TUNING&OPTMIZATION&优化)之——计划重用(plan reusing)

Oracle中,为了减少系统内的硬解析,从而节省系统资源,有绑定变量、计划共享(通过cursor_sharing参数)等一系列措施。那么,SQL Server作为三大商业关系库之一,是否也存在这样的机制呢?答案是肯定的,下面,我们就一起来看看SQL Server系统中的类似机制。

SQL Server主要通过如下四个机制来缓冲之前执行过的查询的执行计划,以避免这些查询的再次编译,从而节省系统资源。

1)临时查询缓冲(Ad hoc query caching);

2)自动参数化(parameterize automatically);

3)准备查询(prepared queries);

4)编译对象(compiled objects);

下面,分别对SQL Server着四个机制介绍如下:

1)临时查询缓冲

SQL Server2005以前,临时计划偶尔也会被缓冲,但是我们不能指望这个特性发挥太多效果。即使后续版本中,当SQL Server缓冲临时计划时,被缓冲的这些计划也只有在随后的批处理文本和这些计划的文本完全匹配时,才能被重用。我们可以通过如下SQL语句来查询被缓冲的临时查询计划的被重用情况:

SELECT usecounts, cacheobjtype, objtype, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = ‘Compiled Plan‘
AND [text] NOT LIKE ‘%dm_exec_cached_plans%‘;

为了改善被缓冲的临时查询计划重用状况不佳的问题,SQL Server提供了一种特性,称之为临时负载优化选项(Optimize for Ad Hoc Workloads option),我们可以通过如下方式开启它:

EXEC sp_configure ‘optimize for ad hoc workloads‘, 1;
RECONFIGURE;

GO

你也可以通过SQL Server management studio中服务器属性的高级页面开启这个特性。该特性被打开后,相同的临时查询第一次被编译时,会在计划缓冲中产生该语句的编译计划根(compiled plan stub),该计划根所占内存空间不会超过300个字节,包含指向该查询文本的指针。当该查询再次被编译时,被缓冲的计划根会被编译计划代替,而该编译计划比原来的计划根要大很多,要占用两个页大小的内存空间。

可以通过如下查询获取该特性开启后,被缓冲的编译计划根和编译计划的信息:

SELECT usecounts, cacheobjtype, objtype, size_in_bytes, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype LIKE ‘Compiled Plan%‘
AND [text] NOT LIKE ‘%dm_exec_cached_plans%‘;

该特性开启后,还可以通过如下命令关闭:

EXEC sp_configure ‘optimize for ad hoc workloads‘, 0;
RECONFIGURE;
GO

也可以通过SQL Server management studio中服务器属性的高级页面关闭该特性。

2)自动参数化

说到参数化,SQL Server又将其分为简单参数化(Simple parameterization)和强制参数化(Forced parameterization)两种情形。这有点类似Oracle中的cursor_sharing参数的使用。下面,我们就先说说简单参数化,简单参数化也是SQL Server的默认设置和行为。有时,SQL Server会地自动将查询中的常数参数化,随后的查询如果和参数化后的查询语句一样,将会重用之前参数化查询的缓冲的执行计划。同样,我们也可以通过如下语句对参数化的行为进行查询和分析:

SELECT usecounts, cacheobjtype, objtype, size_in_bytes, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = ‘Compiled Plan‘
AND [text] NOT LIKE ‘%dm_exec_cached_plans%‘;
GO

结果中,针对每个带常数的查询,会产生一个被缓冲的编译计划,这些临时查询作为壳查询(shell query)的编译计划被缓冲,目的就是为了后续相同常数查询发现查询的参数化版本更容易些,这些常数查询被缓冲的编译计划占用内存空间较小,大概为两个页大小,也并不包含完全的编译计划。而针对所有这些常数查询,系统也会生成一个参数化的查询,该查询称为准备查询(prepared query),这个准备查询的编译计划才是完整的编译计划,因此,占用内存空间也会更大些,大概为四个页大小。

说完了简单参数化,下面,我们说说强制参数化。

有时,你的应用用了很多类似的语句,而且,你认为可能会从编译计划重用中获益,但遗憾的是,系统并不能将这些类似的语句参数化。此时,SQL Server提供了一个数据库选项,那就是PARAMETERIZATION FORCED,可通过如下命令对该选项进行设置:

ALTER DATABASE <database_name> SET PARAMETERIZATION FORCED;

设置该选项后,SQL Server就会将相关查询中常数参数化,但也会有些例外,具体可查询微软官方或其他文档。值得注意的是,这种为了重用缓冲编译计划,将查询中常数一概参数化的做法,有时也可能会带来严重的性能问题,因此,实际应用时,一定要具体问题具体分析。

3)准备查询

如上所述,SQL Server参数化的查询可以在计划缓冲区中生成准备查询类型的编译计划。此外,另外两种方法也可以生成准备查询类型的编译计划。但是,他们和SQL Server参数化的查询不同,这两种方法中用户可以自己决定参数的数据类型。其一是通过T-SQL批处理调用sp_executesql内置过程;其二是通过客户端应用使用准备和执行方法。这两种方法,有点类似Oracle中的绑定变量使用。

sp_executesql过程:使用该过程要求用户确定参数和它们的数据类型,具体语法如下所示:

sp_executesql @batch_text, @batch_parameter_definitions,param1,...paramN

只要通过相同@batch_test和@batch_parameter_definitions参数值调用该过程,就会重用缓冲中的统一编译计划。例如:

EXEC sp_executesql N‘SELECT c2, c3, c4 FROM test.t1 WHERE c1 = @p‘, N‘@p int‘, 1;

EXEC sp_executesql N‘SELECT c2, c3, c4 FROM test.t1 WHERE c1 = @p‘, N‘@p int‘, 2;

EXEC sp_executesql N‘SELECT c2, c3, c4 FROM test.t1 WHERE c1 = @p‘, N‘@p int‘, 3;

准备和执行方法:该方法和sp_executesql过程类似,但不尽相同。该方法并不需要运行时每次都要传送全部批命令文本,而是,只要在准备阶段传送一次即可,然后,返回的句柄可供每次运行批命令时使用。然而,该方法会在计划缓存区生成准备查询的编译计划,但并不会生成类似自动参数化中相应的临时壳查询计划。同样,我们可以通过如下查询获取编译计划相关信息:

SELECT usecounts, cacheobjtype, objtype, size_in_bytes, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = ‘Compiled Plan‘
AND [text] NOT LIKE ‘%dm_exec_cached_plans%‘;
GO

4)编译对象

计划缓存区中,除了包含之前讲到的临时查询编译计划和准备查询的编译计划,还包含第三种编译计划,那就是过程类型(PROC),该类型计划主要由存储过程、用户定义的标量函数和多语句表值函数等,用户可以完全控制这些对象参数的值和类型。这些对象的成功执行,都会重用计划缓存的之前运行的相同对象的编译计划。然而,用户也可以通过选项或重建,来强制这类对象生成新的编译计划,例如:

--存储过程

EXEC P_Test  ‘EM‘;
GO
EXEC P_Test  ‘IN‘;
GO
EXEC P_Test  ‘IN‘ WITH RECOMPILE;

--函数

DECLARE @p1 char(11);
EXEC @p1= test. f_test ‘123456789‘;
SELECT @p1;
GO
DECLARE @p1 char(11);
EXEC @p1 = test. f_test ‘987654321‘;
SELECT @p1;
GO
DECLARE @p1(11);
EXEC @p1 = test.f_test ‘987612345‘ WITH RECOMPILE;

同样,我们可以通过如下查询语句获取编译计划相关信息:

SELECT usecounts, cacheobjtype, objtype, size_in_bytes, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = ‘Compiled Plan‘
AND [text] NOT LIKE ‘%dm_exec_cached_plans%‘;
GO

原文地址:https://www.cnblogs.com/lhdz_bj/p/9208340.html

时间: 2024-10-13 19:50:12

MSSQL优化(TUNING&amp;OPTMIZATION&amp;优化)之——计划重用(plan reusing)的相关文章

深入理解图优化与g2o:图优化篇

前言 本节我们将深入介绍视觉slam中的主流优化方法——图优化(graph-based optimization).下一节中,介绍一下非常流行的图优化库:g2o. 关于g2o,我13年写过一个文档,然而随着自己理解的加深,越发感觉不满意.本着对读者更负责任的精神,本文给大家重新讲一遍图优化和g2o.除了这篇文档,读者还可以找到一篇关于图优化的博客: http://blog.csdn.net/heyijia0327 那篇文章有作者介绍的一个简单案例,而本文则更注重对图优化和g2o的理解与评注. 本

[mysql][【优化集合】mysql数据库优化集合

三个层面: 1.系统层面 2.mysql配置参数 3.sql语句优化 =========================================================== 一.系统层面 =========================================================== 二.mysql参数层面 http://www.oicto.com/mysql-explain-show/ 2.1slowlog 配置slowlog 配置文件: log-slow

利用DBMS_STATS包修改统计信息,欺骗优化器,生成糟糕的执行计划

在使用基于成本的优化器的优化器时,优化器生产执行计划时要估算每条SQL的执行成本,选择最佳的执行计划来执行sql语句.通过操纵统计信息就可以简介操纵执行计划的生成. 当然 需要强调的一点是,这是非常危险的行为 1 创建测试表 SQL> create table test_stats  as   2  select * from dba_objects ; Table created. 2 收集统计信息 SQL> EXEC dbms_stats.gather_table_stats(ownnam

根据自己的需要,把别人开发好的东西搬过来,优化and重构,在优化的过程中,甚至也会弄出一套全新的东西(转)

赵海平在今年三月份来到阿里,听毕玄(他现任主管)说去年五六月份就跟赵海平聊上了.有人问:为啥 BAT 三大巨头,你看中了阿里巴巴?在今天现场达一千多人的分享中赵海平给出了回复:“因为百度和腾讯没找我呗~”,他笑道,“百度以搜索为核心,优化了很多年了,估计也没啥可以优化的了:而腾讯除了 QQ 和微信,也没什么大型应用(别跟人家说哦)”.这不是原话哈,赵海平还是相当谦虚并且能言的,思维很开阔,两个小时的分享内容丰富,时不时还插两个故事,起初进场的手机和电脑都很自觉的收起来了~旁边的同事侃道:“高 P

《Java程序性能优化》学习笔记 Ⅰ设计优化

豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞吐量: 响应时间: 2.木桶定律   系统的最终性能取决于系统中性能表现最差的组件,例如window系统内置的评分就是选取最低分.可能成为系统瓶颈的计算资源如,磁盘I/O,异常,数据库,锁竞争,内存等. 性能优化的几个方面,如设计优化,Java程序优化,并行程序开发及优化,JVM调优,Java性能调

网站推广优化(SEO,网站关键字优化,怎么优化网站,如何优化网站关键字)

网站推广优化教程100条(完整版)下面介绍新手建站推广完美教程,各位根据自己的实际情况酌情选用: 1.准备个好域名.①.尽量在5位数内,当然也不一定,反正要让用户好记.(看个人):②.尽量用顶级的域名,搜索排名感觉好一点.③.做中文站最好用拼音注册,不要问为什么.看百度(baidu.com)就是很好证明.④.域名的安全性,最好选择有些权威的注册商.⑤.好域名或者说主域名最好注册3年以上,因为百度在扒正规站的毛的时候,会看这些资料,他会觉得你不会很快转行的…… 2.网站空间很重要①.速度打开速度慢

Android 性能优化——之控件的优化

Android 性能优化——之控件的优化 前面讲了图像的优化,接下来分享一下控件的性能优化,这里主要是面向自定义View的优化. 1.首先先说一下我们在自定义View中可能会犯的3个错误: 1)Useless calls to onDraw():我们知道调用View.invalidate()会触发View的重绘,有两个原则需要遵守,第1个是仅仅在View的内容发生改变的时候才去触发invalidate方法, 第2个是尽量使用ClipRect等方法来提高绘制的性能. 2)Useless pixel

【SQL server初级】数据库性能优化三:程序操作优化

数据库优化包含以下三部分,数据库自身的优化,数据库表优化,程序操作优化.此文为第三部分 数据库性能优化三:程序操作优化 概述:程序访问优化也可以认为是访问SQL语句的优化,一个好的SQL语句是可以减少非常多的程序性能的,下面列出常用错误习惯,并且提出相应的解决方案 一.操作符优化 1. IN.NOT IN 操作符 IN和EXISTS 性能有外表和内表区分的,但是在大数据量的表中推荐用EXISTS 代替IN . Not IN 不走索引的是绝对不能用的,可以用NOT EXISTS 代替 2. IS 

后端系统性能优化(第一季 3 sql优化)

昨天的博文介绍了如何去发现坏代码,如何优雅的去实现一个应用内的监控程序. 博文地址:后端系统性能优化(第一季 2 找出坏代码) 当然发现了坏代码之后,我们还是要想办法来改掉它,也许它会很顽固.今天说说性能优化的一个非常重要的部分:sql的优化 今天要说的不是怎么来写优秀的,性能好的sql,这些DBA们会比我更加专业.在我们公司,凡是DBA能优化的sql,DBA都在内部消化了,需要反馈给我们的,说明他们可能也束手无策.也是我们该出手的时候了. insert,update这类型的sql,性能一般不会