如何用参数化SQL语句污染你的计划缓存

你的SQL语句的参数化总是个好想法。使用参数化SQL语句你不会污染你的计划缓存——错!!!在这篇文章里我想向你展示下用参数化SQL语句就可以污染你的计划缓存,这是非常简单的!

ADO.NET-AddWithValue

ADO.NET是实现像SQL Server关系数据库数据访问的.NET框架的组成——有一些严重的副作用。不要误解我——只要你正确使用,ADO.NET一直很棒。你马上就会看到,它很容易被错误使用。我们来看下面实现SQL语句执行的C#代码。 

 1 for (int i = 1; i <= 100; i++)
 2 {
 3    val += i.ToString();
 4 
 5    cmd = new SqlCommand(
 6       "SELECT * FROM Sales.SalesOrderDetail WHERE CarrierTrackingNumber = @CarrierTrackingNumber", 
 7       cnn);
 8    cmd.Parameters.AddWithValue("@CarrierTrackingNumber", val);
 9    SqlDataReader reader = cmd.ExecuteReader();
10    reader.Close();
11 }

我们是聪明的开发者,因此SQL语句本身被参数化,因为ADO.NET框架是地球上最棒的框架,我们使用System.Data.SqlClient.SqlParameterCollection类的AddWithValue方法来提供实际的参数值。我在WHLIE循环里运行那个SQL语句100次,总用不同长度赋予参数值。在Sales.SalesOrderDetail表里CarrierTrackingNumber列定义为NVARCHAR(25)。因此我们可以在基于我们提供的不同字符长度上有上至25个不同数据类型的参数。现在让我们检查下我们SQL语句执行后的计划缓存。

1 SELECT
2     st.text,
3     cp.*
4 FROM sys.dm_exec_cached_plans cp
5 CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
6 GO

现在事情变得有点疯狂:在计划缓存里我们存储了100个不同的执行计划!

 

对于每个可能的数据类型参数都有1个执行计划——即使当数据类型是NVACHAR(25)AddWithValue方法非常,非常邪恶:基于你提供的参数值派生出数据类型。永远不要使用它!

ADO.NET – SqlDbType.VarChar

因为从我们的错误中我们学到了,现在我们知道ADO.NET的AddWithValue方法的副作用——我们不再用它。现在让我们重写我们的C#程序代码,如下所示定义一个显示的参数数据类型: 

 1 for (int i = 1; i <= 100; i++)
 2 {
 3    val += i.ToString();
 4 
 5    cmd = new SqlCommand(
 6       "SELECT * FROM Sales.SalesOrderDetail WHERE CarrierTrackingNumber = @CarrierTrackingNumber",
 7       cnn);
 8    cmd.Parameters.Add(new SqlParameter("@CarrierTrackingNumber", SqlDbType.VarChar));
 9    cmd.Parameters["@CarrierTrackingNumber"].Value = val;
10    SqlDataReader reader = cmd.ExecuteReader();
11    reader.Close();
12 }

从代码里你可以看到,ADO.NET现在不能派生参数数据类型了,因为我们已经指定了SqlDbType.Varchar数据类型。让我们再次执行这个SQL语句100次并再次检查下计划缓存:

 

没有啥改变。问题还是一样:在计划缓存里我们还有100个不一样的的执行计划。现在的问题是ADO.NET只强制数据类型(SqlDbType.VarChar),但不是数据类型的"长度"。有100个不同的长度在计划缓存里你就有100个不同的执行计划。

如果你在你的ADO.NET代码里显式指定参数数据类型,你也要指定它的长度!现在我们来看下一些修正的C#代码。

 1 for (int i = 1; i <= 100; i++)
 2 {
 3    val += i.ToString();
 4 
 5    cmd = new SqlCommand(
 6       "SELECT * FROM Sales.SalesOrderDetail WHERE CarrierTrackingNumber = @CarrierTrackingNumber",
 7       cnn);
 8    cmd.Parameters.Add(new SqlParameter("@CarrierTrackingNumber", SqlDbType.VarChar, 100));
 9    cmd.Parameters["@CarrierTrackingNumber"].Value = val;
10    SqlDataReader reader = cmd.ExecuteReader();
11    reader.Close();
12 }

这次我也指定了数据类型的长度——这里是100,现在当我们再次执行SQL语句100次时,最后我们在计划缓存里以1个执行计划且重用了100次来完美收工。这是从SQL Server角度的最终目标。

 

小结

寓意:ADO.NET是个很棒的数据访问框架,它提供你有用的功能(例如AddWithValue方法),当从SQL Server角度来说你真的要考虑下你在做什么。当你使用参数化SQL语句时,你要尽量显式:你必须地冠以参数值的实际数据类型,还有你想要的获得数据类型长度。

感谢关注! 

参考文章:

https://www.sqlpassion.at/archive/2015/07/20/how-to-pollute-your-plan-cache-with-parameterized-sql-statements/

转载于:https://www.cnblogs.com/woodytu/p/4751915.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ios: 如何保護iOS束文件屬性列表,圖像,SQLite,媒體文件

Ios: 如何保護iOS束文件屬性列表&#xff0c;圖像&#xff0c;SQLite&#xff0c;媒體文件我創建了Hello World示例項目&#xff0c;然後添加data.plist文件到資源文件夾。現在人們可以很容易得到束文件解壓縮。國際音標。有任何的方法來保護data.plist文件保存在iPhone應用程序…

w3wp oracle,w3wp.exe占用CPU超过50%的处理

w3wp.exe占用CPU超过50%的处理1.查看CPU占用高的进程&#xff1a;任务管理器C:\Documents andSettings\Administrator>iisappW3WP.exe PID: 18008 AppPoolId: STATW3WP.exe PID: 8328 AppPoolId: STATW3WP.exe PID: 17868 AppPoolId: JYCV16W3WP.exe PID: 16652 AppPoolId: …

论两种学习模式

引言 A&#xff1a;你是如何学习的&#xff0c;通过视频、书籍和实践结合&#xff1f;B&#xff1a;不是&#xff0c;一般情况是以一个问题为点去画线和面。 两种学习模式 按部就班方式获取知识(通过书、视频)缺点 信息接收者缺乏深度思考和探索信息发布者的知识体系不一定适合…

启动mq命令 linux,RocketMQ:Linux下启动server和broker的命令

目录QUESTION:RocketMQ&#xff1a;Linux下启动server和broker的命令?ANSWER:一、启动mqnamesrv1.1当前执行1.2后台运行二、启动mqbroker2.1当前执行2.2后台运行QUESTION:RocketMQ&#xff1a;Linux下启动server和broker的命令?ANSWER:一、启动mqnamesrv1.1当前执行进入rocke…

C++中int *p[4]和 int (*q)[4]的区别

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** C中int *p[4]和 int (*q)[4]的区别 前者是指针数组&#xff0c;后者是指向数组的指针…

linux不用命令开启ssh,不用密码也能ssh登陆Linux?

Linux的一个后门引发对PAM的探究1.1 起因今天在搜索关于Linux下的后门姿势时&#xff0c;发现一条命令如下&#xff1a;ln -sf /usr/sbin/sshd /tmp/su; /tmp/su -oPort5555;经典后门。直接对sshd建立软连接&#xff0c;之后用任意密码登录即可。ssh rootx.x.x.x -p 5555这个是…

ScrollView常用(暂时用上了的)代理方法

2019独角兽企业重金招聘Python工程师标准>>> ScrollView常用代理方法: #pragma mark - 滚动结束调用 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {// 计算 滑动到了第几页double page scrollView.contentOffset.x / scrollView.width;self.p…

Android ListView性能优化实例讲解

前言&#xff1a; 对于ListView&#xff0c;大家绝对都不会陌生&#xff0c;只要是做过Android开发的人&#xff0c;哪有不用ListView的呢&#xff1f; 只要是用过ListView的人&#xff0c;哪有不关心对它性能优化的呢&#xff1f; 关于如何对ListView进行性能优化&#xff0c;…

Bzoj 3289: Mato的文件管理 莫队,树状数组,逆序对,离散化,分块

3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1539 Solved: 665[Submit][Status][Discuss]Description Mato同学从各路神犇以各种方式&#xff08;你们懂的&#xff09;收集了许多资料&#xff0c;这些资料一共有n份&#xff0c;每份有一个大小和一…

vs2010创建和使用动态链接库(dll)

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 本文将创建一个简单的动态链接库&#xff0c;并编写一个应用台控制程序使用该动态链接…

magenta内核与linux,谷歌将推出新操作系统Fuchsia:Magenta语言为内核

谷歌现在研发出来并且推出使用的系统有Chrome OS、Android和Chromecasts&#xff0c;这三者在操作系统的市场中占得份额很高&#xff0c;但是好像谷歌对此并不满意&#xff0c;因为有相关消息显示&#xff0c;谷歌正在研发新的操作系统Fuchsia&#xff0c;该系统采用Magenta语言…

BZOJ 1968: [Ahoi2005]COMMON 约数研究 水题

1968: [Ahoi2005]COMMON 约数研究 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id1968 Description Input 只有一行一个整数 N&#xff08;0 < N < 1000000&#xff09;。 Output 只有一行输出&#xff0c;为整数M…

VC内存对齐准则(Memory alignment)

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 本文所有内容在建立在一个前提下&#xff1a;使用VC编译器。着重点在于&#xff1a;VC…

mysql 主主互备实现

今天星期天&#xff0c;么事就写个MYSQL的主主架构的博客&#xff0c;原理如下图&#xff0c;不是我画的网上找的。主机作用操作系统mysql版本对应IPvip数据库mysqlA(主)centos6.4mysql 5.5.48192.168.48.129192.168.48.126mysqlB(备)centos6.4mysql 5.5.48192.168.48.132一&am…

动手实践 Linux VLAN - 每天5分钟玩转 OpenStack(13)

本节我们来看如何在实验环境中实施和配置如下 VLAN 网络 配置 VLAN 编辑 /etc/network/interfaces&#xff0c;配置 eth0.10、brvlan10、eth0.20 和 brvlan20。 下面用 vmdiff 展示了对 /etc/network/interfaces 的修改 重启宿主机&#xff0c;ifconfig 各个网络接口 用 brct…

Socket的3次握手链接与4次断开握手

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 连接握手&#xff1a; 1.客户端发送建立连接请求 &#xff08;发送请求&#xff09;2.…

Linux桌面需要强制访问控制,RHCSA 系列(十三): 在 RHEL 7 中使用 SELinux 进行强制访问控制...

RHCSA 认证&#xff1a;SELinux 精要和控制文件系统的访问尽管作为第一级别的权限和访问控制机制是必要的&#xff0c;但它们同样有一些局限&#xff0c;而这些局限则可以由安全增强 Linux(Security Enhanced Linux&#xff0c;简称为 SELinux)来处理。这些局限的一种情形是&am…

使用canvas实现擦玻璃效果

体验效果:http://hovertree.com/texiao/html5/25/效果图&#xff1a;代码如下&#xff1a; <!DOCTYPE html> <html> <head lang"zh"> <meta name"viewport" content"initial-scale1.0, maximum-scale1.0, user-scalableno, widt…

[转]opencv学习资料

转自&#xff1a;http://blog.csdn.net/poem_qianmo/article/details/20537737 1&#xff1a;Mat imread(const string& filename, intflags1 ); eg: Mat image0imread("dota.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//载入最真实的图像 ge1i…

jQuery动态设置样式List item

前段时间&#xff0c;Insus.NET有修改一个功能《激活当前视图菜单高亮呈现》http://www.cnblogs.com/insus/p/5287093.html 今天Insus.NET想改用另外一个方法来实现&#xff0c;使用jQuery。在ASP.NET MVC 环境实现&#xff1a; 代码&#xff1a; <ul><li><a hr…