说到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. C#制作RDLC报表

    报表以前我只做过水晶报表,但是最近发现家里的VS上面居然没有水晶报表,发现水晶报表现在貌似已经不能完全免费的使用了,为了保险起见,就用了VS自带的RDLC报表,用完感觉其实也是够用的嘛~ 建立一RDL ...

  2. Visual Studio统计代码行数

    按[Ctrl+Shift+F]弹出查找窗口(不统计以#号开头.以/开头的代码和空行) 1.输入  :b*[^:b#/]+.*$ 2.选择使用正则表达式 3.查找文件类型,*.cs多种类型用分号(;)隔 ...

  3. Java---Java的面试题(一)

    1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节 ...

  4. postgreSQL绝对值

    select * from t where flag=1 order by abs(index) desc

  5. [javaSE] 反射-动态加载类

    Class.forName(“类的全称”) ①不仅表示了类的类类型,还代表了动态加载类 ②请大家区分编译,运行 ③编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 Ⅰ所有的new对象都是静态加载 ...

  6. 每天一命令 git reset

    在使用git的时候不免遇到commit的时候commit了错误的代码的时候,这时候就需要用到git的常用命令之一  reset了. reset顾名思义为重置.重置的是HEAD指针,可以使HEAD指针移 ...

  7. css布局模式

    css布局模型在网页中,元素有三种布局模型: 流动模型(Flow) 浮动模型 (Float) 层模型(Layer) 流动Flow模型(一): 流动(Flow)是默认的网页布局模式.也就是说网页在默认状 ...

  8. [实现]Javascript代码的另一种压缩与加密方法——代码图片转换

    代码=图片 图片=代码 JS代码对于喜欢F12的同志来说,连个遮羞布都没有... 虽然把代码变成图片也仅仅只是增加一层纱布而已...但这方法还是挺好玩的,而且代码也被压缩了一点. 第一次看到[图片=代 ...

  9. [应用][js+css3]3D盒子导航[PC端]

    CSS3构建的3D盒子之导航应用 1.在用css3构建的盒子表面,放上iframe,来加载导航页面. 2.鼠标左键按下移动可旋转盒子,寻找想要的网址. 3.左键单机盒子表面,将全屏现实所点盒子表面的网 ...

  10. CSS的简介

    CSS(Cascading Style Sheets):层叠样式表 层叠:一层一层的 样式表:有很多的属性和属性值 css将网页内容和显示样式进行分离,提高了显示功能 CSS通常被称为CSS样式表或层 ...