这些天看了一篇微软官方发布的MS SQL Server2008性能问题处理及优化的英文文档,里面知识点介绍地很详细,在现实工作中也很实用,遂产生了想把它翻译一下的念头。翻译的过程,既可以帮助自己复习一下这些技术,也可以向其他还不熟悉这一块的朋友介绍一些新的知识,何乐而不为呢。只是这篇文章有点长,我会分成几篇随笔去介绍,所以,不光是对我耐性的考验,也是对你的考验哦!
--------------------------------------------
解决方案
如果你诊断出了过度的编译及重复编译,考虑下面的选择:
--如果重复编译是由SET option改变而导致,使用SQL Server Profiler去确定哪个SET option改变了。避免在存储过程中改变SET options。最好在连接级别去设定它们。确保在整个连接周期内SET options不会改变。
--临时表被激发进行重复编译的阈值要低于正常表。如果发生在临时表上的重复编译是由于统计信息改变,你可以使用表变量替代临时表。表变量的基数改变不会造成重复编译。这种方案的一个不足之处在于,查询优化器不会持续监视表变量的基数信息,因为统计不会再在表变量上创建或者维护。这样做会导致较少的查询优化。你可以测试不同的选项并且选择最好的一种。
--另外一种选择是使用KEEP PLAN 查询提示。这种选择设定临时表具有正常表级别的阈值。EventSubclass列会显示出该临时表“statistics changed”的信息。
--为了避免重复编译是由统计信息改变导致的(例如,如果这个计划变得次优化是由于数据统计信息的改变),指定KEEPFIXED PLAN查询提示。如果这个设定生效的话,重复编译只会在为了确保有效性(例如,基础表结构已经改变并且计划不再应用)并且不响应统计信息的改变时发生。例如,一个重复编译会在查询语句所依赖的表的结构发生变化时发生,或者如果一个表被sp_recompile存储过程标记了。
--关闭这些统计信息的自动更新:索引统计信息及定义在表或者索引视图上的改变后会导致重新编译的统计信息。注意,然而,使用这种方法关闭auto-stats特性,并不是一个很好的注意。这是因为查询优化器不会再对这些对象上的数据改变很敏感,而次优化的查询计划可能会导致。可以这种方法当成是最后一种手段,如果你已经尝试了其它非主流的选择。
--批处理应该有一个完整的对象名(例如,dbo.Table1),以避免重复编译及避免在不同事物之间的含糊不清。
--去避免由于延迟编译导致的重复编译,你应该避免交叉使用DML和DDL或者创建一个使用If进行情况选择的DDL。
--运行Database Engine Tuning Advisor(DTA)去查看是否任意索引改变提升了查询的编译时间和运行时间。
--检查存储过程中是否使用了WITH RECOMPILE选项,在SQL Server 2008及SQL Server 2005中,如果某个存在于该存储过程中的特殊的语句确实需要重复编译,你可能可以使用一个语句级别的 RECOMPILE提示。在语句级别使用这个选项以避免每次都编译整个存储过程,而在同一时间指定单独的语句被编译。更多信息可以查看:query hints