设为首页 收藏本站
查看: 661|回复: 0

[经验分享] 《Microsoft Sql server 2008 Internals》读书笔记--第九章Plan Caching and Recompilation(2)

[复制链接]

尚未签到

发表于 2016-11-7 04:45:51 | 显示全部楼层 |阅读模式
《Microsoft Sql server 2008 Internals》索引目录:  《Microsoft  Sql server 2008 Internals》读书笔记--目录索引
  在这一节,我们将继续关注Adhoc和参数化
  ■Adhoc混合负载的优化
  如果你的查询大多数是临时(adhoc)的,从来不会被重用,似乎浪费内存去缓存这些计划了。SQL Server 2008增加了一个配置选项在这种情况下也能满足你的需求。一旦选项启用,仅仅在第一次任何一个adhoc查询被编译时缓存一个存根,在第二次编译后,存根用以取代全部计划。
  控制为Ad Hoc混合负载设置的优化
  启用选项方法有二:
1、
EXEC sp_configure 'optimize for ad hoc workloads', 1;RECONFIGURE;
2、在SQL Server Management Studio界面,高级-属性-中启用。
DSC0000.jpg
  编译计划存根

  当 optimize for ad hoc workloads启用时,SQL Server缓存的存根仅仅大约300字节,并不包含查询计划的任何部分。它基本上仅仅是一个容器,以保持跟踪某一特殊的查询的前次编译。
这个存根包含了全部的缓存键和一个指向实际查询文本的指针。这个存根被存在SQL Manager缓存中。该存根的usecounts值始终是1,因为从来不会重用。
  当生成编译计划存根的一个查询或批处理被重新编译时,这个存根被全编译计划代替。初始,usecounts被设置为1,因为不确定前一个查询是否与执行计划完全精确相同。
  我们看一个例子:
EXEC sp_configure 'optimize for ad hoc workloads', 1;RECONFIGURE;GOUSE Northwind2;DBCC FREEPROCCACHE;GOSELECT * FROM Orders WHERE CustomerID = 'HANAR';GOSELECT usecounts, cacheobjtype, objtype, [text]FROM sys.dm_exec_cached_plans PCROSS APPLY sys.dm_exec_sql_text (plan_handle)WHERE cacheobjtype LIKE 'Compiled Plan%'AND [text] NOT LIKE '%dm_exec_cached_plans%';GOSELECT * FROM Orders WHERE CustomerID = 'HANAR';GOSELECT usecounts, cacheobjtype, objtype, [text]FROM sys.dm_exec_cached_plans PCROSS APPLY sys.dm_exec_sql_text (plan_handle)WHERE cacheobjtype LIKE 'Compiled Plan%'AND [text] NOT LIKE '%dm_exec_cached_plans%';GO
DSC0001.jpg
DSC0002.jpg
如果关闭选项,执行:
EXEC sp_configure 'optimize for ad hoc workloads', 1;RECONFIGURE;GO
  ■简单参数化(Simple Parameterization)
  对于确定的查询,SQL Server能够决定是否需要把一个或多个常量参数化,此时,遵循相同基本模板的序列查询能够使用相同的计划。例如对于下列查询使用相同的计划:
SELECTFirstName,LastName,TitleFROMEmployees
WHEREEmployeeID=6;
SELECTFirstName,LastName,TitleFROMEmployees
WHEREEmployeeID=2;
SQLServer在内部参数化这两个参数如下:
SELECTFirstName,LastName,TitleFROMEmployees
WHEREEmployeeID=@1;
  
   USE Northwind2GODBCC FREEPROCCACHE;GOSELECT FirstName, LastName, Title FROM Employees WHERE EmployeeID = 6;GOSELECT FirstName, LastName, Title FROM Employees WHERE EmployeeID = 2;GOSELECT usecounts, cacheobjtype, objtype, [text]FROM sys.dm_exec_cached_plans PCROSS APPLY sys.dm_exec_sql_text (plan_handle)WHERE cacheobjtype = 'Compiled Plan'AND [text] NOT LIKE '%dm_exec_cached_plans%';GO
  查询结果类似如下:
DSC0003.jpg
  你应该注意到两个独立的查询由于不同的常量作为临时查询得到了缓存。然而,这些仅仅被考虑为shell queries(盒子查询),它的缓存仅仅使得(在以后相同常量的精准查询而可能被重用时)查找查询的参数化版本容易一些。这个shell查询不包含全部查询计划,而仅仅在相关预备计划中有一个指向全部计划的指针。
  注意:不要把shell查询和计划存根混淆。一个shell查询包含查询的完整文本,使用至少16K内存。Shell查询仅仅被SQL Server认为可参数化的计划创建。而计划存根(plan stub),仅仅在内存中使用200字节,为不可参数化的、临时查询所创建,并且仅仅当optimize for ad hoc workloads选项设置为时生效。
  上图中,注意第三行,objtype为Prepared,注意useCounts为2或4,意味着,一个查询被重用了两次或四次。
  默认情况下,SQL Server对于决定参数自动化是非常保守的。仅仅当查询模板被考虑为安全时才会自动参数化。如果即便实际参数值变化时,一个查询计划也不改变,那么,这个模板是安全的。这个安全原则确保参数化不会消弱查询的性能。上面查询中Employee表有一个惟一的索引,因此任何使用相等比较式的EmployeeID,不会有两行。在惟一索引中使用seek是非常有用的,无论实际值如何。
  然而,考虑到查询可能是一个不等比较式,或一个不惟一的列的相等比较式时。这种情况下,一些实际查询值会返回多行,或没有行,或一行。因此,一个查询是否最好的计划,取决于查询使用的值,是否被认为是安全的,是否参数化。这是整个查询优化的核心。
  除了需求一个查询模板仅仅一个可能的计划外,还有许多查询结构不允许简单参数化,如下:
1、JOIN
  2、BLUK INSERT
  3、IN 列表
  4、UNION
  5、INTO
  6、FOR BROWSER
  7、OPTION<query hints>
  8、DISTINCT
  9、TOP
  10、WAITFOR语句
  11、GROUP BY,HAVING,COMPUTE
  12、全文谓词
  13、序列化(subqueies)
  14、FROM子句(Select语句含有表变量方法或全文表或OPENROWSET或OPENXML或OPENQUERY或OPENDATASOURCE
  15、来自于<>比较谓词
  简单参数化在使用下列结构的修改语句时被禁用:
1、带from子句的Delete/update
  2、带(含变量的)set子句的Update
  ■强制参数化(Forced Parameterization)
  如果你的应用程序使用相同的查询,使用相同的计划明显会改善性能,但却没有自动参数化。或SQL Server出于安全考虑或使用了禁止的结构而没有采用参数化。SQL Server 2008提供了一种替代方案:一个数据库选项(Parameterization forced)
   ALTER DATABASE <database_name> SET PARAMETERIZATION FORCED;
该选项启用时,SQL Server将常量视作参数,有一些例外:
1、INSERT...EXECUTE语句
  2、存储过程、触发器、或用户自定义函数内的语句。SQL Server已经为这些程序重用查询计划。
  3、在客户端已经参数化的预备语句
  4、包含XQuery方法调用的语句(Statements that contain XQuery method calls, where the method appears in a context where its arguments would typically be parameterized, such as a WHERE clause. If the method appears in a context where its arguments would not be parameterized, therest of the statement is parameterized.)
  5、T-SQL游标中的语句(API游标内部的Select语句被参数化)
  6、已经被废弃的查询结构
  7、任何运行在(ANSI_PADDING or ANSI_NULLS设置为Off的)上下文的任何语句
  8、包含超过2097个Literals(直接常量)的语句
  9、引用变量,如Where T.col2>=@p
  10、包含RECOMPILE查询暗示的语句
  11、包含一个COMPUTE子句的语句
  12、包含一个WHERE CURRENT OF的子句
  你需要谨慎为数据库设置这个选项,因为在优化期间所有的常量都参数化,那么频繁重用已经重用的计划将会导致性能急剧下降。
  
  下文将继续关注简单参数化和预查询(Prepared Quries)
邀月注:本文版权由邀月和CSDN共同所有,转载请注明出处。
助人等于自助! 3w@live.cn



  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-296625-1-1.html 上篇帖子: 实验一:SQL server 2005高可用性之----日志传送 下篇帖子: SQL语法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表