SQL临时表和表变量 Declare @Tablename Table

SQL临时表和表变量 Declare @Tablename Table在SQLServer的性能调优中,有一个不可比面的问题:那就是如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择。记得在给一家国内首屈一指的海运公司作SQLServer应用性能评估和调优的时候就看到过大量的临时数据集处理需求,而他们的开发人员就无法确定什么时候用临时表,什么时候用表变量,因此他们就简单的使用了临时表。实际上临时表和表变量都有特定的适用环境。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
在SQL Server的性能调优中,有一个不可比面的问题:那就是如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择。记得在给一家国内首屈一指的海运公司作SQL Server应用性能评估和调优的时候就看到过大量的临时数据集处理需求,而他们的开发人员就无法确定什么时候用临时表,什么时候用表变量,因此他们就简单的使用了临时表。实际上临时表和表变量都有特定的适用环境。

表变量

变量都以@或@@为前缀,表变量是变量的一种,另外一种变量被称为标量(可以理解为标准变量,就是标准数据类型的变量,例如整型int或者日期型DateTime)。以@前缀的表变量是本地的,因此只有在当前用户会话中才可以访问,而@@前缀的表变量是全局的,通常都是系统变量,比如说@@error代表最近的一个T-SQL语句的报错号。当然因为表变量首先是个变量,因此它只能在一个Batch中生存,也就是我们所说的边界,超出了这个边界,表变量也就消亡了。表变量存放在内存中,正是因为这一点所有用户访问表变量的时候SQL Server是不需要生成日志。同时变量是不需要考虑其他会话访问的问题,因此也不需要锁机制,对于非常繁忙的系统来说,避免锁的使用可以减少一部分系统负载。

表变量另外还有一个限制就是不能创建索引,当然也不存在统计数据的问题,因此在用户访问表变量的时候也就不存在执行计划选择的问题了(也就是以为着编译阶段后就没有优化阶段了),这一特性有的时候是件好事,而有些时候却会造成一些麻烦。临时表临时对象都以#或##为前缀,临时表是临时对象的一种,还有例如临时存储过程、临时函数之类的临时对象,临时对象都存储在tempdb中。以#前缀的临时表为本地的,因此只有在当前用户会话中才可以访问,而##前缀的临时表是全局的,因此所有用户会话都可以访问。临时表以会话为边界,只要创建临时表的会话没有结束,临时表就会持续存在,当然用户在会话中可以通过DROP TABLE命令提前销毁临时表。

我们前面说过临时表存储在tempdb中,因此临时表的访问是有可能造成物理IO的,当然在修改时也需要生成日志来确保一致性,同时锁机制也是不可缺少的。跟表变量另外一个显著去别就是临时表可以创建索引,也可以定义统计数据,因此SQL Server在处理访问临时表的语句时需要考虑执行计划优化的问题。表变量 vs. 临时表结论

综上所述,大家会发现临时表和表变量在底层处理机制上是有很多差别的。

简单地总结,我们对于较小的临时计算用数据集推荐使用表变量。如果数据集比较大,如果在代码中用于临时计算,同时这种临时使用永远都是简单的全数据集扫描而不需要考虑什么优化,比如说没有分组或分组很少的聚合(比如说COUNT、SUM、AVERAGE、MAX等),也可以考虑使用表变量。使用表变量另外一个考虑因素是应用环境的内存压力,如果代码的运行实例很多,就要特别注意内存变量对内存的消耗。

一般对于大的数据集我们推荐使用临时表,同时创建索引,或者通过SQL Server的统计数据(Statisitcs)自动创建和维护功能来提供访问SQL语句的优化。如果需要在多个用户会话间交换数据,当然临时表就是唯一的选择了。需要提及的是,由于临时表存放在tempdb中,因此要注意tempdb的调优。

SQL中的临时表和表变量

我们经常使用临时表和表变量,那现在我们就对临时表和表变量进行一下讨论.

临时表

局部临时表

全局临时表

表变量

 临时表

临时表存储在TempDB数据库中,所有的使用此SQL Server 实例的用户都共享这个TempDB,因为我们应该确保用来存储TempDB数据库的硬盘有足够的空间,以使之能够自己的增长.最好能够存储在一个拥有独立硬盘控制器上.因为这样不存在和其它的硬盘I/O进行争用.

我们很多程序员认为临时表非常危险,因为临时表有可能被多个连接所共享.其实在SQL Server中存在两种临时表:局部临时表和全局临时表,局部临时表(Local temp table)以#前缀来标识,并且只能被创建它的连接所使用.全局临时表(Global temp table)以##前缀来进行标识,并且可以和其它连接所共享.局部临时表局部临时表不能够被其它连接所共享的原因其实是在SQL Server 2000中自动为局部临时表的表名后面加上了一个唯一字符来标识.如:

      CREATE TABLE [#DimCustomer_test]

      (

         [CustomerKey] [int]

         ,    [FirstName] [nvarchar](50)  

     ,[MiddleName] [nvarchar](50)  

     ,[LastName] [nvarchar](50)

         )

现在我们来查看一下TempDB中 sysobjects表,我们会发现我们新创建的临时表#DimCustomer_test已经被加上了后缀:

  USE TempDB

   GO

   SELECT name FROM sysobjects WHERE name LIKE ’%DimCustomer%’

the Result is:

name

#DimCustomer_test___________________________________________________________________________________________________000000000005

全局临时表

下面我们来看一下全局临时表:

      CREATE TABLE [##DimCustomer_test]

      (

         [CustomerKey] [int]

         ,       [FirstName] [nvarchar](50)  

     ,[MiddleName] [nvarchar](50)  

     ,[LastName] [nvarchar](50)

         )

现在我们来查看一下TempDB中 sysobjects表,我们会发现我们新创建的临时表##DimCustomer_test没有被加上了后缀:

  USE TempDB

   GO

   SELECT name FROM sysobjects WHERE name LIKE ’%DimCustomer%’

The Result are:

#DimCustomer_test___________________________________________________________________________________________________000000000005

##DimCustomer_test

–Drop test temp tables

                               DROP TABLE [##DimCustomer_test]

                               DROP TABLE [#DimCustomer_test]

可以看到我们刚才创建的全局临时表名字并没有被加上标识.表变量表变量和临时表针对我们使用人员来说并没有什么不同,但是在存储方面来说,他们是不同的,表变量存储在内存中.所以在性能上和临时表相比会更好些!

另一个不同的地方是在表连接中使用表变量时,要为此表变量指定别名.如:

  USE AdventureWorksDW

   GO

   DECLARE @DimCustomer_test TABLE

   (

      [CustomerKey] [int]

      ,       [FirstName] [nvarchar](50)  

,[MiddleName] [nvarchar](50)  

,[LastName] [nvarchar](50)

      )

   —insert data to @DimCustomer_test

   INSERT @DimCustomer_test

   (

      [CustomerKey]  

      ,       [FirstName]  

,[MiddleName]  

,[LastName]

      )

   SELECT  

      [CustomerKey]  

      ,       [FirstName]  

,[MiddleName]  

,[LastName]

   FROM DimCustomer

   SELECT [@DimCustomer_test].CustomerKey,SUM(FactInternetSales.OrderQuantity)

FROM @DimCustomer_test   INNER JOIN FactInternetSales    ON

@DimCustomer_test.CustomerKey = FactInternetSales.CustomerKey

Group BY CustomerKey

Result:

Server: Msg 137, Level 15, State 2, Line 32

Must declare the variable ’@DimCustomer_test’.

如果我们对上面的查询进行更改,对查询使用别名(并且找开IO):

—–in the follow script,we used the table alias.

DECLARE @DimCustomer_test TABLE

(

     [CustomerKey] [int]

     ,       [FirstName] [nvarchar](50)  

,[MiddleName] [nvarchar](50)  

,[LastName] [nvarchar](50)

     )

INSERT @DimCustomer_test

(

     [CustomerKey]  

     ,       [FirstName]  

,[MiddleName]  

,[LastName]

     )

SELECT  

     [CustomerKey]  

     ,       [FirstName]  

,[MiddleName]  

,[LastName]

FROM DimCustomer

SELECT t.CustomerKey,f.OrderQuantity

FROM @DimCustomer_test t INNER JOIN FactInternetSales   f ON

t.CustomerKey = f.CustomerKey

where t.CustomerKey=13513

表变量在批处理结束时自动被系统删除,所以你不必要像使用临时表表一样显示的对它进行删除.

—————————————-

另外在今天帮同事Tuning SQL 脚本地时候,发现对于大数据量表的查询(10w-100W),用变量的方式比用select 的方式居然执行时间减少了100倍!!似懂非懂,但从来没有想到差别如此大,惊讶ing,记录一笔,研究一下

M1:

declare @tempID int

set @tempID =(select lots_id from qs_notes where id=’CVT20080321′)

select * from ls_Qs_notes where id = @tempID

—返回记录998,行执行时间6589

M2:

select * from ls_Qs_notes where id =(select lots_id from qs_notes where id=’CVT20080321′)

—返回记录998 ,行执行时间60

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/171458.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ldd 和ldconfig

    ldd 和ldconfig一、ldconfigldconfig是一个动态链接库管理命令,为了让动态链接库为系统所共享,还需运行动态链接库的管理命令–ldconfig。ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连

    2022年6月11日
    52
  • idea2022最新激活码 csdn【中文破解版】

    (idea2022最新激活码 csdn)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlLGWSVFD4PZ-eyJsaWNlbnNlSW…

    2022年4月1日
    600
  • 为什么要设置环境变量,设置环境变量的作用在哪里[通俗易懂]

    为什么要设置环境变量,设置环境变量的作用在哪里[通俗易懂]1、什么是环境变量引用百度百科里面的解释:环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。看到这里我相信大家可能还是有所疑惑,但是,不急,接着看。2、为什么需要环境变量windows系统下,假如我们安装了某一款软件,安装结束后,在安装目录会生成一个该软件的.exe文件,双击该文件,我们就能启动软件。但是难道我们每次要运行该软件的时候都要先找到该.e

    2022年10月29日
    0
  • Java程序员烂大街了吗?是,也不是

    Java程序员烂大街了吗?是,也不是Java程序员烂大街了吗?有网友吐槽精通的人少,半吊子的人烂大街。半吊子程序员确实不少,除了自身学习有关,还跟培训机构教学有关,工作后能不能继续学造有关,现在学编程的越来越多,所以企业要求相对也比前些年要高很多。  企业想招一个合格的Jjava程序员很不容易。烂大街的说法有网友不怎么赞同,因为市场自己会过,留下好的淘汰掉不合格的。不合格的程序员有一些会放弃,从事别的工作,也有的会坚持学习达到市场的要求。只不过还有很多人在选择进入这个行业而已,很正常的现象。  以前可能知道大概会怎么使用就能找份不

    2022年7月7日
    313
  • jar中没有主清单属性啥意思啊_java命令运行jar找不到主类

    jar中没有主清单属性啥意思啊_java命令运行jar找不到主类1.首先我是用Maven导出到包,得到的jar文件保存在2.在这个文件目录下cmd运行,java-jarcsdn-1.0-SNAPSHOT.jar这句命令提示出现”jar中没有主清单属性”3.解决方法;用压缩包的方式打开jar文件autoUp.class这个是我编译之后得到的class文件main函数在这个里面打开META-INF文件夹,看到MANIFEST.MF文件以记事本的方式打开我的里面一开始是这个样子再里面添加一句代码Main-Class:autoUp

    2022年9月5日
    3
  • 高并发解决方案-代理服务器Nginx[通俗易懂]

    高并发解决方案-代理服务器Nginx[通俗易懂]文章目录Nginx1.Nginx概念2.Nginx的应用场景3.Linux环境下Nginx的安装与启动4.Nginx静态网站部署5.Nginx配置虚拟主机5.1端口绑定5.2域名绑定5.2.1域名概念5.2.2域名级别5.2.3域名与ip绑定6.Nginx反向代理6.1反向代理概念6.2配置反向代理7.Nginx负载均衡7.1负载均衡概念7.2准备工作7.3配置负载均衡Nginx1.Nginx概念    Nginx是⼀款高性能的http服务器/反向代理服务器及电子

    2022年9月29日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号