参数化(三):参数嗅探

参数化(三):参数嗅探

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

    首先我们知道批处理可以是参数化的或者非参数化。参数化的批处理计划有两种类型:“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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 国产linux操作系统深度系统20.3发布(推荐)

    国产linux操作系统深度系统20.3发布(推荐)深度操作系统(deepin)是一个致力于为全球用户提供美观易用、安全稳定服务的Linux发行版,同时也一直是排名最高的来自中国团队研发的Linux发行版。(了解deepin国际排名)深度操作系统20.3,升级Stable内核到5.15版本,进一步提升兼容性。修复系统安全漏洞,增强安全性。部分深度应用新增及优化常用功能,满足不同场景下的使用需求。针对桌面环境部分问题修复及优化,只为带来更好体验。更强大的内核版本Stable内核升级到5.15版本,增强对Intel12代U和NTFS文件系统的支

    2022年5月16日
    42
  • ReleaseMutex函数

    ReleaseMutex函数ReleaseMutex函数的功能是释放互斥对象的控制权函数原型BOOLWIANPIReleaseMutex(HANDLEhMutex);返回值BOOL,TRUE表示成功,FALSE表示失败。参数表hMutex:HANDLE,制定一个互斥体的句柄。注释一个线程释放了互斥对象的控制权后,如果其他进程在等待互斥对象置位,则等待的线程可以得到该互斥对象,等待

    2022年6月26日
    28
  • Springboot项目使用动态切换数据源实现多租户SaaS方案

    Springboot项目使用动态切换数据源实现多租户SaaS方案

    2021年8月31日
    184
  • 表单提交时验证数据是否为空[通俗易懂]

    表单提交时验证数据是否为空[通俗易懂]一、利用submit按钮实现提交,当点击submit按钮时,触发onclick事件,由JavaScript里函数判断输入内容是否为空,如果为空,返回false,不提交,如果不为空,提交到由action指定的地址。<scripttype=”text/javascript”>functioncheck(form){if(form…

    2022年9月13日
    0
  • python怎么把字体调大_python修改字体

    python怎么把字体调大_python修改字体Pycharm4.5是一款非常强大的Python代码编辑器,其具备了易于上手、功能强大等特点,深受广大开发人员的青睐,而在使用的过程中,我们常常需要设置字体的大小以及背景颜色等参数,从而能够为用户带来更好的代码编辑效果,而部分刚入手的用户可能还不知到如何进行设置,小编这里为用户带来了Pycharm4.5设置字体大小与背景颜色的操作操作教程,有需要的用户赶紧来了解一下吧,想必能够为用户带来帮助!方法…

    2022年8月26日
    4
  • pycharm更换账号/pycharm更换jetBrains许可证

    pycharm更换账号/pycharm更换jetBrains许可证pycharm更换jetBrains账号/pycharm更换许可证

    2022年8月27日
    2

发表回复

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

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