Sql Server之旅——第十二站 sqltext的参数化处理
说到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的参数化处理的更多相关文章
- Sql Server之旅——第十四站 深入的探讨锁机制
上一篇我只是做了一个堆表让大家初步的认识到锁的痉挛状态,但是在现实世界上并没有这么简单的事情,起码我的表不会没有索引对吧,,,还 有就是我的表一定会有很多的连接过来,10:1的读写,很多码农可能都会遇 ...
- Sql Server之旅——第十站 看看DML操作对索引的影响
我们都知道建索引是需要谨慎的,当只有利大于弊的时候才适合建,我们也知道建索引是需要维护成本的,这个维护也就在于DML操作了, 下面我们具体看看到底DML对索引都有哪些内幕.... 一:delete操作 ...
- Sql Server之旅——第五站 确实不得不说的DBCC命令
原文:Sql Server之旅--第五站 确实不得不说的DBCC命令 今天研发中心办年会,晚上就是各自部门聚餐了,我个人喜欢喝干红,在干红中你可以体味到那种酸甜苦辣...人生何尝不是这样呢???正好 ...
- (转)Sql Server之旅——第八站 复合索引和include索引到底有多大区别?
索引和锁,这两个主题对我们开发工程师来说,非常的重要...只有理解了这两个主题,我们才能写出高质量的sql语句,在之前的博客中,我所说的 索引都是单列索引...当然数据库不可能只认单列索引,还有我这篇 ...
- SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础
原文:SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础 在前一篇博文中我们学习到了一些关于地理信息的基础知识,也学习了空间参照系统,既地球椭球体.基准.本初 ...
- JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口
JAVA之旅(十二)--Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口 开始挑战一些难度了,线程和I/O方面的操作了,继续坚持 一. ...
- (转)SQLServer_十步优化SQL Server中的数据访问 二
原文地址:http://tech.it168.com/a2009/1125/814/000000814758_all.shtml 第五步:识别低效TSQL,采用最佳实践重构和应用TSQL 由于每个程序 ...
- (转)SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)
二.完整的锁兼容性矩阵(见下图) 对上图的是代码说明:见下图. 三.下表列出了数据库引擎可以锁定的资源. 名称 资源 缩写 编码 呈现锁定时,描述该资源的方式 说明 数据行 RID RID 9 文件编 ...
- SQL Server 性能优化实战系列(二)
SQL Server datetime数据类型设计.优化误区 一.场景 在SQL Server 2005中,有一个表TestDatetime,其中Dates这个字段的数据类型是datetime,如果你 ...
随机推荐
- 通过泛型数据,操作SQL数据库
本人在操作数据库的时候,采用将对象的形式操作传入数据库,经过大量百度和朋友帮助,总结出如下两个接口.用于插入数据,提取数据. 要这样操作的前提条件,就是类名和表名一致,类字段和表字段一致就可以了 // ...
- 关联查询 join on 和比较运算符 in
join on多表之间的关联查询 写法select 字段 from 表1 t join 表2 s on t.字段1 = s.字段1 where 条件: 也可以这么写select 字段 from 表1 ...
- java.lang.IllegalStateException: Failed to read Class-Path attribute from manifest of jar file:/XXX
出现这个问题的解决方案就是将原有的jar删除 然后重新下载过一遍就可以使用了 我估计是元数据等损坏了
- Slick – 这是你需要的最后一款 jQuery 传送带插件
slick 是一款完全响应式的 jQuery 传送带插件,能够根据容器自动适应宽度.在现代浏览器中会使用 CSS3 来实现特殊效果,可以使用扩展方法对项目进行添加.删除和过滤.这是你需要的最后一款 j ...
- browser.html – HTML 实现 Firefox UI
browser.html 是一个实验性的项目,用于证明一个概念:使用 HTML 重新实现 Firefox UI ,并作为一个应用程序.它是基于浏览器的 API ,并以浏览器的方式和系统的应用工作.即使 ...
- 【追寻javascript高手之路05】理解事件流
前言 新的一天又开始了,我们对今天对未来抱有很大期待,所以开始我们今天的学习吧,在此之前来点题外话,还是爱好问题. 周三的面试虽然失败,但是也是很有启迪的,比如之前我就从来没有想过爱好问题,我发现我的 ...
- Windows服务器如何选 搭建WAMP环境
Windows Server 2003 Windows Server 2008 如何选择服务器系统版本.原文地址:http://www.xwamp.com/learn/1. 系统版本: Windows ...
- 安装 Ubuntu 后的个人常用配置
在 ASA 猪队友的带领下,拥抱开源世界,用上了Ubuntu.资深强迫症现身说法,配置符合自己使用习惯的Ubuntu. 1. 窗口标题栏显示菜单项 打开系统设置->外观->行为,在[显示窗 ...
- 渗透测试常规思路分析-FREEBUF
最基础但练得好最后也非常厉害 1. 主要由于服务器配置等原因造成的信息泄露 常用google ,bing等搜索工具,轻量级的搜索出一些遗留后门,不想被发现的后台入口,中量级的搜索出一些用户信息泄露, ...
- Python学习02 列表 List
Python学习02 列表 List Python列表 List Python中的列表(List)用逗号分隔,方括号包围(comma-separated values (items) between ...