SQL参数化查询的另一个理由 命中执行计划

1概述

SQL语言的本质就是一串伪代码,表达的是做什么,而不是怎么做的意思。如其它语言一样,SQL语句需要编译之后才能运行,所以每一条SQL是需要通过编译器解释才能运行的(在这之间还要做SQL的优化)。而这些步骤都是需要运行成本,所以在数据库中有一个叫做执行计划的东西,编译器会将编译过后的SQL存入执行计划当中,当遇到同样的SQL时,就直接调用执行计划来执行,而不需要再次编译。

通过对上面执行计划的认识,为了提高数据库运行的效率,我们需要尽可能的命中执行计划,这样就可以节省运行时间。

2相关SQL

2.1查看当前数据库中所有的执行计划:

复制代码 代码如下:

SELECT cp.usecounts AS '使用次数'

,objtype AS '类型'

,st.[text] AS 'SQL文本'

,plan_handle AS '计划句柄'

FROM sys.dm_exec_cached_plans cp

CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st

WHERE st.text not like '%sys%'

2.2删除执行计划

复制代码 代码如下:

--删除所有计划

DBCC FREEPROCCACHE

2.3测试脚本(创建员工表,并向其插入1000条数据)

复制代码 代码如下:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Employee]'))

DROP TABLE [dbo].Employee

GO

--人员表

CREATE TABLE dbo.Employee

(

id int,

name nvarchar(50)

);

--插入测试数据

DECLARE @I INT=0,@ENDI INT=1000;

WHILE(@I<@ENDI)

BEGIN

SET @I+=1;

INSERT dbo.Employee(id,name) VALUES(@I,'蒋大华'+CAST(@I AS NVARCHAR(20)));

END;

3测试执行计划

3.1 先执行删除所有执行计划,然后执行SELECT * FROM Employee ,最后查看执行计划(2.1中的查看执行计划脚本)如下图

即SQL SERVER会为每一条SQL建立一个执行计划,并将它缓存起来

3.2 再运行一次SQL: SELECT * FROM Employee,并查看执行计划

可以看到这个计划的重用次数为2,即这个计划被重用了;

3.3 修改SQL:SELECT  * FROM Employee(在SELECT后多加一个空格),执行并查看执行计划

结果又新添加一个执行计划,即SQL SERVER认为这是两个不同的SQL语句并分别建立了执行计划;

4重用执行计划——使用参数化查询方法

4.1 未参数化SQL

复制代码 代码如下:
string selectCmdText = string.Format(@"SELECT * FROM Employee WHERE name='{0}'",” 蒋大华1”);
SQLHelper.ExecuteNonQuery(SQLHelper.DefaulConnectiontString, System.Data.CommandType.Text, selectCmdText, null);

查看执行计划:

即当执行一个未参数化SQL时,SQL SERVER需要先将其转换成一个参数SQL并执行它。一共需要两执行计划

然后再执行下面的代码(查询的条件变了)
复制代码 代码如下:
string selectCmdText = string.Format(@"SELECT * FROM Employee WHERE name='{0}'",” 蒋大华2”);
SQLHelper.ExecuteNonQuery(SQLHelper.DefaulConnectiontString, System.Data.CommandType.Text, selectCmdText, null);

查看执行计划

此时不需要再准备一个准备的SQL,但还是需要再产生一个执行计划,并缓存下来;

4.2 参数化SQL
复制代码 代码如下:
SqlParameter[] param = { new SqlParameter("@name", txtEmployeeName.Text.Trim()) };
string selectCmdText = string.Format(@"SELECT * FROM Employee WHERE name=@name");
SQLHelper.ExecuteNonQuery(SQLHelper.DefaulConnectiontString, System.Data.CommandType.Text, selectCmdText, param);

输入参数并执行,然后查看执行计划:

只需要一个准备SQL,然后,输入不同的参数,并执行,再查看执行计划

重用执行计划,perfect...

5总结

总的来说,SQL语句在执行时,会生成执行计划并将它缓存起来,我们可以通过提高使用缓存中的执行计划次数,来减少数据库的压力。而使用参数化的SQL是一个很好的选择,参数化查询的作用不仅只有防止SQL注入,还可以提高缓存中执行计划使用次数。

时间: 2024-11-10 22:50:18

SQL参数化查询的另一个理由 命中执行计划的相关文章

SQL参数化查询的另一个理由 命中执行计划_MsSql

1概述 SQL语言的本质就是一串伪代码,表达的是做什么,而不是怎么做的意思.如其它语言一样,SQL语句需要编译之后才能运行,所以每一条SQL是需要通过编译器解释才能运行的(在这之间还要做SQL的优化).而这些步骤都是需要运行成本,所以在数据库中有一个叫做执行计划的东西,编译器会将编译过后的SQL存入执行计划当中,当遇到同样的SQL时,就直接调用执行计划来执行,而不需要再次编译. 通过对上面执行计划的认识,为了提高数据库运行的效率,我们需要尽可能的命中执行计划,这样就可以节省运行时间. 2相关SQ

SQL SERVER 2014 下IF EXITS 居然引起执行计划变更的案例分享

  这个问题是在SQL SERVER 2005 升级到SQL SERVER 2014的测试过程中一同事发现的.我觉得有点意思,遂稍微修改一下脚本展示出来,本来想构造这样的一个案例来演示,但是畏惧麻烦,遂直接贴上原表,希望 Leader不要叼我(当然个人觉得真没啥,两张表名而已,真泄露不了啥信息).     脚本如下所示,非常简单的一段SQL语句,我将其分为SQL1.SQL2.SQL3.  其实SQL2.SQL3是差不多的,唯一的区别在于多了一个IF EXISTS DECLARE @Operati

MySQL5.6:一个神奇的执行计划

今天遇到一个非常神奇的sql执行计划时好时坏,我们一起来领略一下吧 废话不多说,直接进入实战 环境 * version:MySQL5.6.27 社区版 * 表结构 CREATE TABLE `xx` ( `TagId` int(11) NOT NULL AUTO_INCREMENT COMMENT '', `TagType` int(11) DEFAULT NULL COMMENT '', `SubType` int(11) DEFAULT NULL COMMENT '', `CommId` i

SQL Server中如何清除特定语句的执行计划缓存

SQL server运行到一定的时候, 执行计划的缓存可能会相当大,有些能到几个GB的大小.这个时候假设某个语句比较复杂而且SQL server 生成的执行计划不够优化,你希望把该执行计划的缓存清除使得SQL server能够重新编译该语句.该如何做呢? 如果是存储过程则很好办,直接使用sp_recompile就可以了,如下所示.如果参数是表,那么所有用到该表的存储过程或http://www.aliyun.com/zixun/aggregation/17067.html">trigger都

SQL Server查询优化器:最佳执行计划

我们知道,查询优化器的基本的目标就是为我们的查询语句找出一个比较高效的执行计划.即使是一个非常简单的查询,也会存在很多的不同方式去访问数 据,而这些不同的方式都是可以得到相同的结果的,所以,查询优化器必须要很"明智的"从这些大量的执行计划中找出了一个"最佳"的出来. 前一篇:浅析SQL Server查询优化器的工作原理 为了得到最好的计划,查询优化器必须在某些条件的限制下,尽可能多的创建和评估大量的候选执行计划.看到这里,就有一点需要注意了"查询优化器是尽

参数化查询为什么能够防止SQL注入

多数人知道SQL注入,也知道SQL参数化查询可以防止SQL注入,可为什么能防止注入却并不是很多人都知道的. 首先:我们要了解SQL收到一个指令后所做的事情: 在这里,简单的表示为: 收到指令 -> 编译SQL生成执行计划 ->选择执行计划 ->执行执行计划. 具体可能有点不一样,但大致的步骤如上所示. 接着我们来分析为什么拼接SQL 字符串会导致SQL注入的风险呢? 首先创建一张表Users: CREATE TABLE [dbo].[Users]( [Id] [uniqueidentif

SQLServer 参数化查询经验分享

什么是参数化查询? 一个简单理解参数化查询的方式是把它看做只是一个T-SQL查询,它接受控制这个查询返回什么的参数.通过使用不同的参数,一个参数化查询返回不同的结果.要获得一个参数化查询,你需要以一种特定的方式来编写你的代码,或它需要满足一组特定的标准. 有两种不同的方式来创建参数化查询.第一个方式是让查询优化器自动地参数化你的查询.另一个方式是通过以一个特定方式来编写你的T-SQL代码,并将它传递给sp_executesql系统存储过程,从而编程一个参数化查询.这篇文章的后面部分将介绍这个方法

在ADO.NET中用参数化查询缩短开发时间

ado 一段时间以来,存储过程一直是企业应用程序开发数据访问的首选方法.存储过程的安全性更高.封装能力更强,并能执行复杂的逻辑,且不会打乱应用程序代码.但是,它也存在一些缺点: • 开发者倾向于在存储过程中加入商业逻辑. • 更改过程时必须改变开发环境. • 查找过程所需的参数比较费时. • 许多时候,存储过程提供的功能超出所需. 嵌入到应用程序代码中的内联SQL代码是数据访问的另一个常见方法.虽然企业在开发过程中很少用到这种方法,但许多小型项目应用这种类型的数据访问方法.应用内联SQL可以实现

SQLServer 参数化查询经验分享_MsSql

什么是参数化查询? 一个简单理解参数化查询的方式是把它看做只是一个T-SQL查询,它接受控制这个查询返回什么的参数.通过使用不同的参数,一个参数化查询返回不同的结果.要获得一个参数化查询,你需要以一种特定的方式来编写你的代码,或它需要满足一组特定的标准. 有两种不同的方式来创建参数化查询.第一个方式是让查询优化器自动地参数化你的查询.另一个方式是通过以一个特定方式来编写你的T-SQL代码,并将它传递给sp_executesql系统存储过程,从而编程一个参数化查询.这篇文章的后面部分将介绍这个方法