说到sql的参数化处理,我也是醉了,因为sql引擎真的是一个无比强大的系统,我们平时做系统的时候都会加上缓存,我想如果没有缓存,就不会有什么

大网站能跑的起来,而且大公司一般会在一个东西上做的比较用心,比较细,sqlserver同样也使用了缓存,其中就包括Data cache 和Plan cache两个大头。

现在我们也知道了Plan cache包括上一篇生成的xml结构和sql text,更有趣的是,sql text 还可以做到参数化。。。也就是模板化了。。

一:Sql参数化

<1> 先来做一个Person表,插入1000条数据,然后清空下缓存,再select出一个数据,如图:

 DROP TABLE dbo.Person
CREATE TABLE Person(ID INT IDENTITY,NAME CHAR(5) DEFAULT 'aaaaa')
INSERT INTO dbo.Person DEFAULT VALUES
go 1000 DBCC freeproccache
SELECT * FROM dbo.Person WHERE ID=100

<2> 数据已经查询出来了,下面我们看下dm_exec_sql_text中的sql会是怎样?

 SELECT usecounts,objtype,cacheobjtype, plan_handle,query_plan,text FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE text LIKE '%Person%'

从上面的图中可以看到,当我select一下后,出现了两个sql text,第一个叫Adhoc(即时查询),一个叫Prepared(参数化),然后我点击第二个记录

的query_plan,会出现图形化的执行计划,如下图:

跟着好奇心,我继续点击第三个记录的query_plan会是怎样???

通过这两个sql text的执行计划,不知道你观察出来下面四点了没有:

(1) 我的sql是执行表扫描的,这个没有问题,问题在于我的两个sql text中,第一个plan居然没有完整的执行计划,而仅仅是一个图形化的select,

第二个参数化sql,它的plan是一个完整的执行计划。。。那这说明什么呢???既然Prepared是完整的执行计划,那干嘛还要把adhoc这个

sql缓存起来呢???其实这个我也不清楚。。。我猜测肯定是让引擎快速的找到prepared这个完整的执行计划吧。。。

(2)  就是想为什么sqltext要做参数化,仔细想想应该明白参数化的目的就是为了重用执行计划,因为这时候的xml已经生成好了,不然的话,你

每次执行的sql中只要参数不同都要生成一次query_plan的xml,是不是会拉查询速度的后腿呢???

(3)   你有没有关注到参数化的类型是tinyint,看到这个tinyint我马上就想破它了,我们知道tinyint就是byte类型,表示的范围也就到256...也许

    引擎看我where 100才觉得我好欺负。。。那我现在想法就是where 500,看看会是什么效果???

 SELECT * FROM dbo.Person WHERE ID=500

 SELECT usecounts,objtype,cacheobjtype, plan_handle,query_plan,text FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE text LIKE '%Person%'

从图中可以看到,当我where 500的时候,引擎会再次生成一个prepared的sqltext,这样就有两个prepared了,那我在想,为什么不直接

   给一个(@1 int)呢???像目前这样sql引擎的处理方式,会有几条prepared记录的xml和sqltext的,是不是有点浪费内存呢?

(4)  仔细想想你会知道,sql引擎还是挺色胆包天的,因为prepared的记录已生成,执行计划也就生成了。。。。那说明什么呢???说明这时候

  的xml已经是死的了,也就说明执行计划也是定死的了,难道@1参数的不同不会导致执行计划有变更么???如果有变更难道还让我执行原来

这个表扫描执行计划么???有点奇葩,好了,我准备在下面仔细说说。

二:参数的变化对prepared的影响

  如果你看过之前的博文,你应该明白有一个叫做书签查找的玩意。。。它的原理是在非聚集索引上通过B树查找,当查找到目标键的时候拿到这

个键的聚集索引key,然后通过key来取数据的记录,如果你的非聚集索引的键值的唯一性比较高,这时候sql引擎会走书签查找,但是如果你的键值

唯一性比较低或者在数据量比较小的情况,sql引擎就不会走书签查找,而转向聚集索引扫描。。。那这说明什么呢?说明执行计划在有些时候会跟

(@1 int)这个值有关系。。。那这样的话貌似就不能重用执行计划了,对吧。。。。为了验证sql引擎怎么处理的,我们来做一个测试。

1.先清空缓存,再在Name列上建索引,然后我们select下,如下图:

 DBCC freeproccache
CREATE INDEX idx_Name ON dbo.Person(NAME)
SELECT * FROM dbo.Person WHERE NAME='aaaaa'

2. 然后还是继续看看xml和sqltext

你有什么发现吗?在记录中并没有发现什么prepared记录,这说明什么。。。说明sqlserver很聪明,它知道Name可能会有 “表扫描”到

“书签扫描”的来回切换,为了验证问题,我继续向Person表插入1w条数据,然后再插入一个唯一性数据。如下图:

 INSERT INTO dbo.Person DEFAULT VALUES
go 10000
INSERT INTO dbo.Person(NAME ) VALUES ('ccccc')

确实,如我猜想的一样,sqlserver很聪明的。。。如果它觉得这个Name不靠谱的话,它是绝对不敢给这条sqltext生成prepared的。。。转过

头来再想想第一条为什么会有sqltext,那是因为a列不管取值多少,都改变不了走表扫描的现实,所以sql引擎才敢这么大胆。。。突然觉得人生

不就是这样嘛????很多人都是不把稳的事情是绝对不敢做的。。。

Sql Server之旅——第十二站 sqltext的参数化处理的更多相关文章

  1. Sql Server之旅——第十四站 深入的探讨锁机制

    上一篇我只是做了一个堆表让大家初步的认识到锁的痉挛状态,但是在现实世界上并没有这么简单的事情,起码我的表不会没有索引对吧,,,还 有就是我的表一定会有很多的连接过来,10:1的读写,很多码农可能都会遇 ...

  2. Sql Server之旅——第十站 看看DML操作对索引的影响

    我们都知道建索引是需要谨慎的,当只有利大于弊的时候才适合建,我们也知道建索引是需要维护成本的,这个维护也就在于DML操作了, 下面我们具体看看到底DML对索引都有哪些内幕.... 一:delete操作 ...

  3. Sql Server之旅——第五站 确实不得不说的DBCC命令

    原文:Sql Server之旅--第五站 确实不得不说的DBCC命令 今天研发中心办年会,晚上就是各自部门聚餐了,我个人喜欢喝干红,在干红中你可以体味到那种酸甜苦辣...人生何尝不是这样呢???正好 ...

  4. (转)Sql Server之旅——第八站 复合索引和include索引到底有多大区别?

    索引和锁,这两个主题对我们开发工程师来说,非常的重要...只有理解了这两个主题,我们才能写出高质量的sql语句,在之前的博客中,我所说的 索引都是单列索引...当然数据库不可能只认单列索引,还有我这篇 ...

  5. SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础

    原文:SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础 在前一篇博文中我们学习到了一些关于地理信息的基础知识,也学习了空间参照系统,既地球椭球体.基准.本初 ...

  6. JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口

    JAVA之旅(十二)--Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口 开始挑战一些难度了,线程和I/O方面的操作了,继续坚持 一. ...

  7. (转)SQLServer_十步优化SQL Server中的数据访问 二

    原文地址:http://tech.it168.com/a2009/1125/814/000000814758_all.shtml 第五步:识别低效TSQL,采用最佳实践重构和应用TSQL 由于每个程序 ...

  8. (转)SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)

    二.完整的锁兼容性矩阵(见下图) 对上图的是代码说明:见下图. 三.下表列出了数据库引擎可以锁定的资源. 名称 资源 缩写 编码 呈现锁定时,描述该资源的方式 说明 数据行 RID RID 9 文件编 ...

  9. SQL Server 性能优化实战系列(二)

    SQL Server datetime数据类型设计.优化误区 一.场景 在SQL Server 2005中,有一个表TestDatetime,其中Dates这个字段的数据类型是datetime,如果你 ...

随机推荐

  1. input为disabled提交后得不到该值的解决方法

    input的字段当为diabled时时无法获取数值得,所以最近不要用这个,我们可以用readonly带替代,即可解决这类问题 放在form表单中提交后得不到该值. 将disabled=”disable ...

  2. 《Java4Android》视频学习笔记——包和访问权限(一)

    怎么打包?代码如下 package org.marsdroid; class Test{ public static void main(String args[]){ System.out.prin ...

  3. [moka同学笔记]Yii2.0显示页匿名函数设置$value

    匿名函数设置$value <?= GridView::widget([ 'dataProvider' => $dataProvider, 'columns' => [ // ['cl ...

  4. 三星s4刷机教程(卡刷)

    ···············使用到的工具···················手机助手(--推荐91助手).root精灵.Odin3 v3.07.recovery包.rom包 1.首先在电脑上安装9 ...

  5. Android填坑系列:在小米系列等机型上放开定位权限后的定位请求弹框

    背景: 近期因实际项目需要,在特定操作下触发定位请求,取到用户位置及附近位置. 问题: 经初步选型,最终决定接入百度定位,按照百度定位SDK Android文档,接入过程相对顺利.但随后发现,在小米系 ...

  6. 配置WCF Test Client

    用vs2010建立了一个wcf项目,通过F5直接运行那服务文件,就出现了一个”The dependent tool 'svcutil.exe' is not found“, , 之后想通过“tool- ...

  7. 使用Apache的Hex类实现Hex(16进制字符串和)和字节数组的互转

    包名称:org.apache.commons.codec.binary 类名称:org.apache.commons.codec.binary.Hex 1.字节数组(byte[])转为十六进制(Hex ...

  8. css知多少(10)——display

    1. 引言 网页的所有元素,除了“块”就是“流”,而且“流”都是包含在“块”里面的(最外层的body就是一个“块”).在本系列一开始讲<浏览器默认样式>的时候,大家也都看到了浏览器默认样式 ...

  9. jbox演示30种不同的调用方法

     在线预览 插件说明 - jbox 是一款基于 jQuery 的多功能对话框插件,能够实现网站的整体风格效果,给用户一个新的视觉享受. 运行环境 - 兼容 IE6+.Firefox.Chrome.Sa ...

  10. Seen.js – 使用 SVG 或者 Canvas 渲染 3D 场景

    Seen.js 渲染3D场景为 SVG 或者 HTML5 画布.Seen.js 包含对于 SVG 和 HTML5 Canvas 元素的图形功能的最简单的抽象.所有这个库的其它组件都是不用关心将要渲染的 ...