sql server 存储过程的优化.(变量表,临时表的简单分析)


1.变量表:

declare @t table
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert  @t
select top 10000 id,supno,eta from 表

这一句执行sql需时间:16806ms

2.临时表:

create table #t
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert #t
select top 10000 id,supno,eta
from 表

这一句执行sql需时间:76ms

3.不创建临时表,直接插入到临时表

select top 10000 id,supno,eta
into #t
from 表

这一句执行sql需时间:30ms

通过以上的分析,可以非常清晰的看出那个优,那个劣了。

以上只是简单的分析了一下。所以在存储过程中尽量合作临时表来存储临时数据,不要使用变量表。

那么表变量一定是在内存中的吗?不一定.

通常情况下,表变量中的数据比较少的时候,表变量是存在于内存中的。但当表变量保留的数据较多时,内存中容纳不下,那么它必须在磁盘上有一个位置来存储数据。与临时表类似,表变量是在 tempdb 数据库中创建的。如果有足够的内存,则表变量和临时表都在内存(数据缓存)中创建和处理。

 说明:

     1) CPU-- 事件(sql语句)使用的 CPU 时间(毫秒)。

     2)  Reads--由服务器代表事件读取逻辑磁盘的次数。这些读取操作数包含在语句执行期间读取表和缓冲区的次数。

     3) Writes--由服务器代表事件写入物理磁盘的次数。

 

示例1.变量表

1) 10000条记录

declare @t table
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert  @t

select top 10000 ID,supno,eta from 表

 

--cpu :125    reads :13868    writes: 147

--表 '#286302EC'。扫描计数 0,逻辑读取 10129 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

--表 '表'。扫描计数 1,逻辑读取 955 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

declare @t table
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert  @t

select top 1000 ID,supno,eta from 表

 

--    cpu:46    reads:2101     writes:    17   
--表 '#44FF419A'。扫描计数 0,逻辑读取 1012 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--表 '表'。扫描计数 1,逻辑读取 108 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。



--示例2。临时表:

 

create table #t
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
end
insert #t
select top 10000 ID,supno,eta
from 表

--cpu :125    reads:13883       writes:148    
--表 '#t00000000005'。扫描计数 0,逻辑读取 10129 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--表 '表'。扫描计数 1,逻辑读取 955 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。


create table #t
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)

insert #t
select top 1000 ID,supno,eta
from 表

--cpu: 62    reads: 2095        writes: 17

--表 '#t00000000003'。扫描计数 0,逻辑读取 1012 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--表 '表'。扫描计数 1,逻辑读取 108 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。


 


--示例3。不创建临时表,直接插入到临时表

select top 10000 ID,supno,eta
into #t
from 表

--cpu:31    reads:1947        writes:83

--表 '表'。扫描计数 1,逻辑读取 955 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。




select top 1000 ID,supno,eta
into #t
from 表

--cpu: 0    reads: 997        writes:11

--表 '表'。扫描计数 1,逻辑读取 108 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

从以上的分析中可以看出,如果使用3)方式,则会少建一个临时表.那么IO中的读写也将减少次数.

1)与2)都会有先建临时表的动作,并进行相应的IO读取操作.

从sql语句对服务器的cpu使用上来看,第三种情况cpu使用率也相对较低.

从物理写入磁盘操作来看,第三种情况的物理写入次数较少.

 

在什么情况下使用表变量来代替临时表:

取决于以下三个因素:

插入到表中的行数。本人认为最好是小于1000行,具体情况具体分析.
从中保存查询的重新编译的次数。
查询类型及其对性能的指数和统计信息的依赖性。

在某些情况下,可将一个具有临时表的存储过程拆分为多个较小的存储过程,以便在较小的单元上进行重新编译。

个人建议,当记录行小于1000行的情况下,应尽量使用表变量,除非数据量非常大(大于1000行)并且需要重复使用表。在这种情况下,可以在临时表上创建索引以提高查询性能。但是,各种方案可能互不相同。

Microsoft 建议您做一个测试,来验证表变量对于特定的查询或存储过程是否比临时表更有效。

 

 

转自: http://www.cnblogs.com/chillsrc/archive/2007/08/31/877073.html

 


存储过程的安全及性能优化 存储过程分类  系统存储过程  自定义存储过程SQL Server使用者编写的存储过程  扩展存储过程  动态链接库(DLL)函数的调用看,主要用于客户端和服务器端之间进行通信  exec master..xp_cmdshell 'dir *.exe' -- 执行目录命令查询[sql2005\sql2008]  exec master..xp_fixeddrives --列出硬盘分区各自可用空间  xp_regwrite根键,子键,值名,值类型,值【sql2008拒绝访问】  写入注册表,例如:  exec master..db.xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\run','TestValueName','reg_sz','hello'  xp_regdeletevalue 根键,子键,值名【sql2008拒绝访问】  删除注册表某个值  xp_regdeletekey键,值【sql2008拒绝访问】  删除该键下包括的所有值 xp_cmdshell语法  xp_cmdshell {'command_string'} [,no_output]  command_string是在操作系统命令行解释器上执行的命令字符串。command_string数据类型为varchar(255)或者nvarchar(4000),没有默认值  no_output为可选参数,可以控制是否想客户端返回信息  该存储过程一般情况下被禁用的,需要手动开启使用,如下:  exec sp_configure 'show advanced options',1  go   reconfigure  go   exec sp_configure 'xp_cmdshell',1—1表示启用,0表示禁用  go   reconfigure  go 删除xp_cmdshell SQL SERVER200删除xp_cmdshell use master exec sp_dropextendedproc 'xp_cmdshell' go SQL SERVER2005以上禁用xp_cmdshell,但不能删除掉 exec sp_configure 'xp_cmdshell',0 —1表示启用,0表示禁用  go reconfigure --让sp_configurre立即生效  go  exec sp_configure 'show advanced options',0  go   reconfigure  go --注意:SQL SERVER2008考虑安全性很多存储过程直接被拒绝访问 恢复/启用扩展存储过程 SQLServer2000 use master exec sp_addextendedproc xp_cmdshell,'xplog70.dll' go SQL Server2005或SQL Server2008启用xp_cmdshell  exec sp_configure 'show advanced options',1  go   reconfigure  go   exec sp_configure 'xp_cmdshell',1—1表示启用,0表示禁用  go   reconfigure  go 扩展存储过程的定义  扩展存储过程SQL Server中的另一类存储过程,它是以其它语言编写的外部程序,是以动态链接库(DLL)形式存储在服务器上,最终SQLServer就可以动态加载并执行它们  编写好后使用SQLServer的固定角色sysadmin注册该扩展存储过程,并将执行权限授予其它用户,这个扩展存储过程只能添加到master数据库。  在编写扩展存储过程中可能要用到某些系统存储过程,这些系统存储过程如下: 利用OLE自动化存储过程调用dll 1.创建类库程序集 namespace PB_ExtendProcedure { public class ExtendProcedure { public string SayHi() { return "hello world"; } } } 2.生成动态链接库并注册到系统中 2.1.生成动态链接库使用VS2010命令行工具 使用sn命令生成一个强命名文件: sn -k helpkey.snk 使用csc生成dll csc /t:library /keyfile:helperkey.snk ExtendProcedure.cs 向系统注册这个dll regasm /tlb:ExtendProcedure.tlb ExtendProcedure.dll /codebase 2.2.SQL Server中编写扩展存储过程 --sp_OACreate --sp_OAMethod --sp_OADestroy --sp_OAGetErrorInfo 流程: DECLARE @object int --返回创建的对象 DECLARE @hr int --过程返回值 DECLARE @return varchar(255) --dll方法的返回值 DECLARE @src varchar(255),@desc varchar(255) ---过程的错误原因、描述 --1.创建对象 EXEC @hr = sp_OACreate 'PB_ExtendProcedure.ExtendProcedure',@object out IF @hr0 BEGIN EXEC sp_OAGetErrorInfo @object,@src,@desc out select hr = convert(varchar(4),@hr),Source=@src,Description=@desc return END --2.调用方法 EXEC @hr = sp_OAMethod @object,'SayHi',@return out IF @hr0 BEGIN EXEC sp_OAGetErrorInfo @object,@src,@desc out select hr = convert(varchar(4),@hr),Source=@src,Description=@desc return END print @return --3.销毁对象实例 EXEC @hr = sp_OADestroy @object IF @hr0 BEGIN EXEC sp_OAGetErrorInfo @object,@src,@desc out select hr = convert(varchar(4),@hr),Source=@src,Description=@desc return END 注意:默认情况sqlserver2008是禁止调用ole自动化存储过程的,解决方法如下: sp_configure 'show advanced options',1 go reconfigure go sp_configure 'ole automation procedures',1 go reconfiugre go 加密存储过程 创建加密存储过程语法 CREATE PROCEDURE WITH ENCRYPTION AS 存储过程执行机制 语法阶段:指创建存储过程时,系统检查其创建语句语法正确性的过程。若语法检查通过则系统将该存储过程存储在当前数据库的sys.sql_modules目录视图当中 解析阶段:指某个存储过程首次执行时,查询处理器从sys.sql_modules目录视图中读取该存储过程的文本并且检查该过程引用的对象是否存在的过程。 编译阶段:指分析存储过程和生成存储过程执行计划的过程。执行计划是来描述存储过程执行过程的。查询优化器是在分析存储过程之后将生成的执行计划存储在存储过程高速缓冲存储器中,此后每次调用已经创建的存储过程时将直接执行不再需要编译,这样就可以提高程序的运行性能。 执行阶段:指执行驻留在存储过程高速缓冲存储区中的存储过程执行计划的过程。 了解SQL Server Profiler SQL Server Profiler是图形化实时监视工具 能帮助系统管理员监视数据库和服务器行为,比如死锁数量、致命错误 跟踪T-SQL语句和存储过程 通常使用Profiler监视重要事件: 登录连接的失败 成功或断开连接 delete、insert、update命令 存储过程开始或结束 存储过程中的每一条语句 写入sql server错误日志的错误 打开游标 向数据对象添加或释放锁 Profiler事件 SQL Server Profiler里Standard模板的事件类 数据库引擎优化顾问介绍 引擎优化顾问提供数据库系统的优化建议,经过管理员修改达到优化目的 引擎优化顾问分析数据库的工作负荷【Sql Server Profiler的跟踪文件或者表】和物理实现 引擎优化顾问提出合理的物理设计结构以降低工作负荷的开销 数据库引擎优化顾问介绍 引擎优化顾问提供数据库系统的优化建议,经过管理员修改达到优化目的 引擎优化顾问分析数据库的工作负荷【Sql Server Profiler的跟踪文件或者表】和物理实现 引擎优化顾问提出合理的物理设计结构以降低工作负荷的开销 提高存储过程性能方法 存储过程里面包含很多语句,我们真正要提高性能的是存储过程里面这些语句  默认情况存储过程会返回每条语句执行后的影响行数,如果不需要这些信息的话,可以使用SET NOCOUNT ON来终止这种返回行为,这样可以避免客户端和服务器之间多次进行信息传递的过程。  减少可选参数:频繁使用可选参数是很容易降低性能的。  优化SQL语句  避免频繁访问同一张或多张表,尤其是数据量大的表  尽量避免大事务操作  尽量避免使用游标,游标效率很差,如果使用游标就不要在游标的循环中使用表连接操作  注意where语句的写法,应该根据索引的顺序、范围的顺序、范围的大小来确定条件子句的前后顺序,尽量让字段顺序与索引顺序保持一致  尽量使用exists代替select count()判断是否存在记录  注意表之间连接的数据类型  先写DDL,再写DML: 当DML先于DDL执行的时候,SQL Server会重新编译存储过程,因为DML引用了DDL中的一些内容,也就是所谓的一些表。这个时候SqlServer需要统计由DDL定义的一些对象的变化。以此来创建DML的执行计划,如果将DDL放在前面那么这种编译只需要以此就可以了。  合理使用索引: 根据实际查询需求来创建索引 尽量使用索引字段做查询条件 尽量避免对大数据量表进行全表扫描,可考虑新建索引  合理使用tempdb系统表 尽量避免使用distinct、order by、group by、having、join语句--这些语句加重tempdb的负担  避免频繁创建和删除临时表临时表中插入数据过大,可使用select into 代替 create table  使用了临时表,要在存储过程最后显式删除  避免使用大临时表与其他大数据量表的连接查询和修改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值