数据库参数化模式数据库参数化有两种方式,简单(simple)和强制(forced)。默认参数化默认为“简单”。在简单模式下,如果每次发送SQL,除非完全相同,否则会重新编译(特殊情况会自动参数化,这是本文的重点)。强制模式是强制对adhocSQL进行参数化,避免adhocSQL每次运行都要参数化。值不同重新编译,这里不做详细说明。首先感谢大神“潇湘隐士”的提醒。当时,我也遇到了一个实际问题。我发现执行计划中数据行的估计是错误的。我观察到无论参数怎么改,SQL语句都没有重新执行。编译,我一头雾水,这个问题是由于简单参数化模式下某些SQL自动参数化,导致执行计划重用,也是本文的重点。我以前写过这个问题。那时候只是理论性的看。我没有考虑它的影响。此参数是数据级选项。设置请参考下图。什么情况下会自动参数化简单参数在优化模式下,SQLServer会自动参数化只有一种执行模式的AdhocSQL语句,从而达到重用执行计划的目的。后面会说明哪些类型的SQL会被自动参数化。自动参数化有什么问题在简单模式下,SQL会自动参数化一些SQL,避免每次都重新编译。SQLServer自动参数化SQL语句的行为可以避免一些重编译,这本来是出于“好意”,但这种“好意”往往并不总能给我们带来好处。例如为了说明什么情况下会自动参数化首先创建一个简单的测试环境createtableTestAuotParameter(idintnotnull,col2varchar(50))GOdeclare@iint=0while@i100000begininsertintoTestAuotParametervalues(@i,NEWID())set@i=@i+1endGOcreateuniqueindexidx_idonTestAuotParameter(id)GO自动参数化SQL语句是因为SQL语句select*fromTestAuotParameterwhereid=33333(66666,99999)有而且只有一个高效的执行方式(也就是索引查找)这里是一个也只有一个方式就是量表中的数据比较大,而且因为索引idx_id是唯一的。如果不是唯一的,那么情况就不同了。让我解释一下有什么,下面的截图显示了一个有效的执行计划:在同一个测试中,我删除了id上的***索引并将其创建为非***索引。再做同样的测试,你会发现同样的SQL的执行并没有自动参数化。我在这里解释一下原因。索引类型与执行计划缓存有何关系?对于非***索引,做索引查找可能效率高,做全表扫描可能效率高(比如某个ID的数据分布特别大)。这时候执行计划可能是多种多样的,不仅只有一种方式,所以SQL自动参数化自动参数化没有问题不用多说,自动参数化的好处就不多说了,因为缓存执行plan可以复用,避免了每次参数值不同都要重新编译的问题。说到执行计划重用,不得不说的话题之一就是参数嗅探。这是一个已经磨损的问题。是的,自动参数化会因为参数不同而重用第一次编译生成的执行计划,这很可能会造成parametersniff。这个问题,以及从参数嗅探派生的其他问题,也用一个例子来证明。这个问题是我最近在观察执行计划统计(statistics)估计问题时遇到的问题。这让我困惑了一会儿。在此再次感谢潇湘隐士。这个问题也是由于SQL语句的自动参数化,导致执行计划的复用,造成极简单的SQL在某些情况下执行效率低下的情况。automatic参数之所以和上面类似,是因为在有且只有一种执行方式(索引查找)的情况下,不同参数的执行计划的复用导致数据行的估计错误。测试前清空缓存执行计划,观察不同查询条件下的实际执行计划。预估数据行如下:1、初始查询条件为:CreateDate>'2016-6-1'andCreateDate2,更新查询条件为:CreateDate>'2016-6-1'andCreateDate3,更新查询conditionto:CreateDate>'2016-6-1'andCreateDatefoundno,因为查询时间段变了,实际行数也变了,但是不管实际行数,估计行数是始终是第一次执行的估计行数。一定是错的吧?不管带什么条件,估计行数都是37117,当时就懵了。为什么每次执行SQL时数据行的预估都是一样的?其实这个问题和一开始的例子一样,因为sql语句自动参数化,导致执行计划被重用,执行计划被重用,导致数据行数估计不正确实际上查询。如何解决自动参数化导致的执行计划重用不正确的问题很多问题找到了真正的原因,解决起来往往并不难。出现这个问题的原因是执行计划的复用导致的,所以我们只需要解决执行计划复用的问题即可。能。那就是防止他重用执行计划,只需要在SQL语句中加一个hint,就是:selectCOUNT(1)fromTest20160810whereCreateDate>'2016-6-1'andCreateDateOPTION(RECOMPILE)的原因是加上添加OPTION(RECOMPILE)查询提示后,SQL执行计划缓存不缓存。没有执行计划缓存,就没有必要重用它。重新编译SQL语句,他可以正确估计出数据行。小结本文通过一个实际案例来说明什么是简单参数模式下的自动化参数,自动化参数会带来哪些问题,以及如何解决。问题本身很简单。如果你不注意,你仍然会偶尔感到困惑。题外话我有一个很深的感触,就是说,越来越多的实际问题必须要有理论知识的支持,但往往理论情况并不经常出现,或者即使出现也不引起人们的注意。忽略了一些理论知识。对于遇到的问题,如果真的想弄明白,还是需要一些理论知识来铺垫的。很多时候,遇到问题之后,回想起来好像看到了这方面的理论知识。这就是为什么我们需要坚持看书,了解一些理论知识。
