SQL参数化查询的另一个理由——命中执行计划_Mssql数据库教程
推荐:一列保存多个ID(将多个用逗号隔开的ID转换成用逗号隔开的名称)背景:在做项目时,经常会遇到这样的表结构在主表的中有一列保存的是用逗号隔开ID。如,当一个员工从属多个部门时、当一个项目从属多个城市时、当一个设备从属多个项目时,很多人都会在员工表中加入一个deptIds VARCHAR(1000)列(本文以员工从属多个部门为例),用以保
1概述
SQL语言的本质就是一串伪代码,表达的是做什么,而不是怎么做的意思。如其它语言一样,SQL语句需要编译之后才能运行,所以每一条SQL是需要通过编译器解释才能运行的(在这之间还要做SQL的优化)。而这些步骤都是需要运行成本,所以在数据库中有一个叫做执行计划的东西,编译器会将编译过后的SQL存入执行计划当中,当遇到同样的SQL时,就直接调用执行计划来执行,而不需要再次编译。
通过对上面执行计划的认识,为了提高数据库运行的效率,我们需要尽可能的命中执行计划,这样就可以节省运行时间。
2相关SQL
2.1查看当前数据库中所有的执行计划:
2.2删除执行计划
- 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.3测试脚本(创建员工表,并向其插入1000条数据)
- --删除所有计划
- DBCC FREEPROCCACHE
3测试执行计划
- 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.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注入,还可以提高缓存中执行计划使用次数。
分享:经典SQL语句大全一、基础 1、说明:创建数据库 CREATE DATABASE database - name 2、说明:删除数据库 drop database dbname 3、说明:备份sql server -- - 创建 备份数据的 device USE master EXEC sp_addumpdevice ' disk ' , ' testBack ' , ' c:\mssql7backup\MyNwind_1.dat ' --
- sql 语句练习与答案
- 深入C++ string.find()函数的用法总结
- SQL Server中删除重复数据的几个方法
- sql删除重复数据的详细方法
- SQL SERVER 2000安装教程图文详解
- 使用sql server management studio 2008 无法查看数据库,提示 无法为该请求检索数据 错误916解决方法
- SQLServer日志清空语句(sql2000,sql2005,sql2008)
- Sql Server 2008完全卸载方法(其他版本类似)
- sql server 2008 不允许保存更改,您所做的更改要求删除并重新创建以下表
- SQL Server 2008 清空删除日志文件(瞬间日志变几M)
- Win7系统安装MySQL5.5.21图解教程
- 将DataTable作为存储过程参数的用法实例详解
- 相关链接:
- 教程说明:
Mssql数据库教程-SQL参数化查询的另一个理由——命中执行计划。