使用SQL2005强制计划解决遗留系统性能问题

       面对遗留系统或第三方系统在程序中编写的SQL语句出现性能问题时,因没有相应的程序代码,在SQL2000下你也只能束手无措。SQL2005提供了强制计划的功能,可以部分的优化这些遗留语句的性能问题。为什么说部分呢?因为强制计划的选项只能使用OPTION里的提示。因此它只能优化部分ad-hoc查询和部分参数化的语句,这也是为什么要使用存储过程的重要性了。下面以一个示例来演示一下强制计划的三个制作步骤:

  1. 捕获程序中发出的ad-hoc或参数化查询语句
  2. 使用 SET STATISTICS XML得到优化后的执行计划
  3. 使用USE PLAN查询提示使用新的执行计划

强制计划的制作其实很简单,关键在于第2步怎么样生产一个最优的计划。

为了演示方便我们先在tempdb下执行以下脚本:

Code

如果我们想查询c=999并且b>102d=10并且b>102的记录,这个查询很简单。 程序中代码如下所示:

Code

1.使用profile查看该语句的执行计划如下,对表t做了一次表扫描。因为这个表现在只占用了一个数据页,因此它选择了表扫描是正确的。在此不讨论计划的正确性,只演示如何改变执行计划。

使用SQL2005强制计划解决遗留系统性能问题

2.那现在该使用STATISTICS XML制作我们自己的执行计划了,如下语句所示:

Code

点击结果集中的XML把所得到的执行计划保存下来。这也是最重要的一步,改变SQL语句得到相同的结果,充分利用现有索引。

3.制作强制计划

如果程序中是直接拼接的SQL语句,中间要多一步强制参数化的操作。要不然只能改变生成计划时匹配参数的语句。因此必须要进行强制参数化。但是强制参数化有时是适得其反的,进行强制参数化时一定要小心。

Code

因为程序中已经参数化,所以可以直接使用在profiler中捕获到的语句:

exec sp_executesql N'SELECT * FROM t WHERE b > @b AND (c = @c OR d = @d)',N'@b int,@c int,@d int',@b=102,@c=99,@d=10  

把语句和参数部分分别赋给对应的参数,把第2步中得到的计划放在USE PLAN提示中。需要注意StatementText属性中如果有'时,一定要手工把它替换为''''。还有一定要使用从profiler中捕获的语句,尤其是在使用ad-hoc查询时,因为语句任何不一致都会导致生成另外的执行计划,所以在测试这类语句时一定要注意格式、大小写、空格等要一致。下面的语句可以创建一个强制计划:

Code

执行完强制计划后,再来运行一下程序从profiler中得到如下的结果,说明我们的计划生效了。还有一点要注意的是:如果SqlParameter在定义参数时没有指定参数类型,随着参数的变化,跟踪到的参数化查询中会自动生成不同的参数类型,这时你必须要为所有的参数类型组合才能使得计划有效。

使用SQL2005强制计划解决遗留系统性能问题

 

你可能感兴趣的:(sql2005)