参数化(三):参数嗅探

参数化(三):参数嗅探

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

    首先我们知道批处理可以是参数化的或者非参数化。参数化的批处理计划有两种类型:“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表的行数。如果大多数国家有差不多的行数,而且大多数执行使用了这些国家,那么参数嗅探是很好的事情,因为大多数情况执行计划是适用的,并且比不带参数嗅探的计划要好(未知参数)。另一方面,如果国家的值的分布不是均匀的,那么一个国家编码的参数很有可能对于其他国家的查询计划就是一个糟糕的选择,此时参数嗅探就是不好的事情了。

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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android Studio中 HAXM安装失败的问题(Intel HAXM installation failed. To install Intel HAXM follow the…)

    Android Studio中 HAXM安装失败的问题(Intel HAXM installation failed. To install Intel HAXM follow the…)AndroidStudio:IntelHAXMinstallationfailed.ToinstallIntelHAXMfollowtheinstructionsfoundat:xxxxHAXM:Thesystemrequirementsarenotsatisfied

    2022年6月28日
    288
  • js 字符串截取(包含中英文)

    js 字符串截取(包含中英文)有一个项目中需要兼容ie6,在使用ztree中很难修改符合ie下面的字符截取样式,于是使用js方法来截取,字符串截取推荐使用: //截取字符串包含中文处理     //(串,长度,增加…)     functionsubString(str,len,hasDot){      varnewLength=0;    

    2022年6月6日
    57
  • webstrom激活码2021_在线激活

    (webstrom激活码2021)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月30日
    143
  • RGBD深度相机_rgbd相机是什么

    RGBD深度相机_rgbd相机是什么深度相机与RGBD相机的区别?为何经常概念混淆?什么是深度图? 什么是深度/RGB-D相机(有什么关系?)? RGB-D相机原理简介结构光 飞行时间RGB-D相机有哪些坑? RGB-D相机优点 RGB-D相机应用深度图一般是16位的单目结构光?双目结构光?单目结构光有一个红外发射器和一个红外接收器双目结构光有一个红外发射器和两个红外接收器…

    2026年1月16日
    4
  • ringbuffer的常规用法_c语言fputs

    ringbuffer的常规用法_c语言fputs一、ringBuffer介绍ringBuffer称作环形缓冲,也有叫circleBuffer的。就是取内存中一块连续的区域用作环形缓冲区的数据存储区。这块连续的存储会被反复使用,向ringBuffer写入数据总是从写指针的位置开始,如写到实际存储区的末尾还没有写完,则将剩余的数据从存储区的头开始写;从该ringBuffer读出数据也是从读指针的位置开始,如读到实际存储区的末尾…

    2025年10月25日
    4
  • Java 持久层概述

    Java 持久层概述JDBCJavaData 是一系列接口规范 Java 程序都是通过 JDBC 连接数据库的 然后通过其执行 SQL 对数据库进行操作 DBC 只是 Sun 公司定义的接口规范 具体实现是交由各个数据库厂商去实现的 因为每个数据库都有其特殊性 这些是 Java 规范没办法确定的 importjava sql importjava util logging Level importjava util logging Logger publicclas

    2025年11月17日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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