参数化(三):参数嗅探

参数化(三):参数嗅探

    在之前的随笔中我提到过参数嗅探,这是非常重要的概念。下面我们深入的研究一下参数嗅探…

    首先我们知道批处理可以是参数化的或者非参数化。参数化的批处理计划有两种类型:“Prepared” 或者“Proc”。前者对应带有至少一个参数的sys.sp_executesql的执行,并且从T-SQL批处理,或者应用程序通过ADO.NET等直接被执行的。后者的执行计划对应一个存储过程。

    参数嗅探在这两种类型中是完全相同的。它的行为在两种计划中是完全一样的。因此我们这里不去讨论类型,只关心参数化批处理本身的作用。

 

什么是参数嗅探?

 

    当批处理包含一个或者多个参数时并且它需要优化(例如因为没有该批处理执行计划缓存,或者只有不可用的计划),优化器知道参数的值。意味着优化器可以使用参数值去估计计划中每个步骤返回的行数。就好像参数的值被硬编码到批处理的文本中。这就是参数嗅探。

    这是很有用的,因为如果优化器不知道参数的值,它将被迫去猜测返回的行数。基于平均统计和其他使用的元数据来尽可能准确地猜测,但是大多数时候仍然与真实行数相去甚远。错误的估计导致选择低效的执行计划并导致很差的性能。

    例如,一个批处理第一次被执行,首先编译,因为对应计划在计划缓存中没有。在编译时,由于有参数嗅探,参数的值将被用来生成执行计划。当计划被创建时,计划被放在缓存中用来重用。下次相同的批处理被执行时,虽然有可能用了不同的参数,但是缓存中的计划仍将被重用。当然,第二次执行的结果将基于参数的值。但是执行第二次的计划是与第一次一样的,这个计划就是来自于第一次执行的参数。

<span>参数化(三):参数嗅探</span>

    如上图。在参数化批处理的实际执行计划的图形表示中,查看最外层的操作符属性(通常是一个select操作符),然后找到“Parameter List”属性。展开属性时,将会看到每个参数编译时和运行时的值。编译时的值就是参数嗅探用来生成计划的参数。运行时的值是实际在指定计划中的参数。

    实际上,第二次执行可能是性能很差的,因为优化器在两次生成计划时估计返回数据的行数可能是相差大的。这里纯粹是运气,没有更好地方式。执行计划被参数的值决定,而我们不能控制它,因为不知道编译何时放生。如果计划对于大多数执行时很高效的,那么一切ok,但是如果它不是呢?假使用户用一个很少使用的参数来执行存储过程,这个参数值产生一个执行计划,并且对于指定该值作为参数的执行是非常高效的。但是其他参数时将会表现很糟糕。

因此问题来了:参数嗅探是好还是不好?

    一如往常,答案就是:“看情况”。这取决于数据的分布。让我们看一下之前用的存储过程:

CREATE PROCEDURE
    Marketing.usp_CustomersByCountry
(
    @Country AS NCHAR(2)
)
AS

SELECT
    Id ,
    Name ,
    LastPurchaseDate
FROM
    Marketing.Customers
WHERE
    Country = @Country;
GO

 

    这种情况下,使用参数@Country,来过滤行customers表的行数。如果大多数国家有差不多的行数,而且大多数执行使用了这些国家,那么参数嗅探是很好的事情,因为大多数情况执行计划是适用的,并且比不带参数嗅探的计划要好(未知参数)。另一方面,如果国家的值的分布不是均匀的,那么一个国家编码的参数很有可能对于其他国家的查询计划就是一个糟糕的选择,此时参数嗅探就是不好的事情了。

   那么我们在参数嗅探是否有益这件事情上能做什么?下一章将介绍如何高效的使用参数嗅探。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119726.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JavaScript正则表达式的两种写法[通俗易懂]

    JavaScript正则表达式的两种写法[通俗易懂]JavaScript正则表达式可以使用正则表达式的特殊符号(//)来声明,也可以采用正则表达式对象(RegExp)来声明。1、使用正则表达式符号正则表达式符号为”//”,即为2个斜杠,中间为匹配规则。JavaScript中类似的特殊符号还有数组“[]”,对象“{}”。示例:      functionprintln(str){         document

  • mysql创建视图sql语句_MySQL 视图

    mysql创建视图sql语句_MySQL 视图视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义。视图不直接存储数据,不知真正的表。关系型数据库中的数据是由一张一张的二维关系表所组成,简单的单表查询只需要遍历一个表,而复杂的多表查询需要将多个表连接起来进行查询任务。对于复杂的查询事件,每次查询需要输入SQL命令,重复且低效,视图可以大大降低查询的重复性。

    2022年10月24日
  • mysql重置root密码linux_linux怎么重置root密码

    mysql重置root密码linux_linux怎么重置root密码为数据库用户修改密码是DBA比较常见的工作之一。对于MySQL用户账户的密码修改,有几种不同的方式,推荐的方式使用加密函数来修改密码。本文主要描述了通过几种不同的方式来修改用户密码以及mysqlroot账户密码丢失(重置root密码)的处理方法。1、密码修改的几种方法a、可以在创建用户的时候指定密码,以及直接使用grant创建用户的时候指定密码。  对于已经存在的用户直接使用grant方式也可

  • goland激活码最新【2021免费激活】

    (goland激活码最新)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

  • js编写桌面应用_web桌面应用框架

    js编写桌面应用_web桌面应用框架最近要做个桌面的应用,用起来也方便。找了一圈发现NW.js挺容易上手,分享给大家。NW.js官网https://nwjs.io/1.下载适合当前版本的js【这里下载的SDK版本,方便后续调试】

  • matlab画折线图,标记指定点「建议收藏」

    matlab画折线图,标记指定点「建议收藏」首先,找到你需要标注的点。比如说你有x、y两个列向量构成一条曲线。现在要找最大值点那么用p=find(y=max(y)),那么坐标(x(p),y(p))就是你要找的点咯。2第二步如何标记。我介绍两总方法来标记这个点,但是总体上可以归结为一种方法。(1)利用text(x(p),y(p),’o’,’color’,’g’));这里o表示标注的形状,也可以用*、^等比较好看的符号哟。’g’表示的是颜色。(…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号