透明 发表于 2015-1-16 14:07:10

Sql Server中一时表与表变量剖析

这能找出所有错误的99.99%。它不能找出的是仅仅涉及数据文件的损坏(这很不常见)。如果你想要检查一张表,你通常应该没有选项地运行myisamchk或用-s或--silent选项的任何一个。在SQLServer的功能调优中,有一个不成对比的成绩:那就是怎样在一段必要长工夫的代码或被频仍挪用的代码中处置一时数据集?表变量和一时表是两种选择。记得在给一家国际压倒一切的海运公司作SQLServer使用功能评价和调优的时分就看到过大批的一时数据集处置需求,而他们的开辟职员就没法断定甚么时分用一时表,甚么时分用表变量,因而他们就复杂的利用了一时表。实践上一时表和表变量都有特定的合用情况。
先矫饰一些基本的常识:表变量
变量都以@或@@为前缀,表变量是变量的一种,别的一种变量被称为标量(能够了解为尺度变量,就是尺度数据范例的变量,比方整型int大概日期型DateTime)。以@前缀的表变量是当地的,因而只要在以后用户会话中才能够会见,而@@前缀的表变量是全局的,一般都是体系变量,好比说@@error代表比来的一个T-SQL语句的报错号。固然由于表变量起首是个变量,因而它只能在一个Batch中保存,也就是我们所说的界限,超越了这个界限,表变量也就灭亡了。
表变量寄存在内存中,恰是由于这一点一切用户会见表变量的时分SQLServer是不必要天生日记。同时变量是不必要思索其他会话会见的成绩,因而也不必要锁机制,关于十分忙碌的体系来讲,制止锁的利用能够削减一部分体系负载。
表变量别的另有一个限定就是不克不及创立索引,固然也不存在统计数据的成绩,因而在用户会见表变量的时分也就不存在实行企图选择的成绩了(也就是觉得着编译阶段后就没有优化阶段了),这一特征有的时分是件功德,而有些时分却会形成一些贫苦。

一时表
一时工具都以#或##为前缀,一时表是一时工具的一种,另有比方一时存储历程、一时函数之类的一时工具,一时工具都存储在tempdb中。以#前缀的一时表为当地的,因而只要在以后用户会话中才能够会见,而##前缀的一时表是全局的,因而一切用户会话都能够会见。一时表以会话为界限,只需创立一时表的会话没有停止,一时表就会延续存在,固然用户在会话中能够经由过程DROPTABLE命令提早烧毁一时表。
我们后面说过一时表存储在tempdb中,因而一时表的会见是有大概形成物理IO的,固然在修正时也必要天生日记来确保分歧性,同时锁机制也是不成短少的。
跟表变量别的一个明显往别就是一时表能够创立索引,也能够界说统计数据,因而SQLServer在处置会见一时表的语句时必要思索实行企图优化的成绩。

表变量vs.一时表
表变量一时表数据集的存储地位内存(不思索被换到页面文件这类情形)磁盘(不思索会见后被缓存到内存中)是不是必要日记否是是不是能够创立索引


是不是可使用统计数据


是不是能够在多会话中会见


是不是必要锁机制


结论
综上所述,人人会发明一时表和表变量在底层处置机制上是有良多不同的。
复杂地总结,我们关于较小的一时盘算用数据集保举利用表变量。假如数据集对照年夜,假如在代码顶用于一时盘算,同时这类一时利用永久都是复杂的全数据集扫描而不必要思索甚么优化,好比说没有分组或分组很少的聚合(好比说COUNT、SUM、AVERAGE、MAX等),也能够思索利用表变量。利用表变量别的一个思索要素是使用情况的内存压力,假如代码的运转实例良多,就要出格注重内存变量对内存的损耗。
一样平常关于年夜的数据集我们保举利用一时表,同时创立索引,大概经由过程SQLServer的统计数据(Statisitcs)主动创立和保护功效来供应会见SQL语句的优化。假如必要在多个用户会话间互换数据,固然一时表就是独一的选择了。必要说起的是,因为一时表寄存在tempdb中,因而要注重tempdb的调优。
再议SQLServer一时表和表变量
对存储的需求:表变量和一时表都损耗Tempdb中的存储空间,可是举行数据更新的时分,表变量不会写日记,而一时表则会写日记。(这一点是经由剧本测试的,表变量其实不像我们设想的那样,只写在内存而不呈现在Tempdb中。)
对优化的撑持:表变量不撑持索引和统计数据,一时表则能够撑持索引和统计数据。
一般必要表变量大概一时表的情形都是一些必要撑持一时盘算了局集的中央,那末就有一些罕见的情形了:
假如一时了局集仅仅必要往内里写数据,好比经由过程一个轮回屡次查找相干数据并分解一个一时了局集,那末就能够利用表变量。(了局有人提到了前往了局集的时分必要有排序,可是表变量不撑持索引阿。实在这个没关系,由于表变量固然不撑持索引,可是表变量撑持主键阿,以是能够使用主键来替换索引。)
假如一时了局集不太多必要变动,而是更多地充任一个一时的联系关系数据集往列入各类数据集的毗连(JOIN),那末索引和统计数据大概会加倍合适一些(固然这个一时了局集要充足年夜,如许索引和统计数据带来的价值才能够被填补失落)。
因为表变量不撑持统计数据,因而在一个存储过程当中利用表变量能够削减因为数据变更而招致的从头编译成绩。
固然,除索引和统计数据这个分明的限定外,表变量同时也不撑持并行实行企图,因而关于年夜型的一时了局集,表变量也不是一个好的选择。
后面一个关于表变量和一时表的贴子,有一名robi_xu的伴侣提到的成绩也的确是在选择表变量和一时表时分的一些成绩。
关于函数中不克不及撑持一时表是因为函数不克不及对函数感化域内部的资本形态形成永世性的变动,在SQLServer中也称为反作用(sideeffect)。不外假如在函数中利用年夜型的一时了局集是不保举的,由于假如将如许的函数安排到一个查询中会形成很分明的功能成绩,因而这类情形一样平常都接纳存储历程之类的批处置剧本。
关于静态剧本不撑持表变量的缘故原由是由于存储历程不承受表范例的参数。不外假如表变量的声明和赋值都在sp_executesql的参数中的话,sp_executesql就能够实行了,由于这个时分表变量就存在sp_executesql的stmt参数内里,不必要传进,比方上面的代码:(固然如许的有用性也就没有几了)

DECLARE@mnvarchar(max)
SET@m=NDECLARE@tTABLE(IDint);INSERTINTO@tVALUES(1);SELECT*FROM@tT
EXECsp_executesql@m
为多种编程语言提供了API。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。

只想知道 发表于 2015-1-16 15:45:27

Sql Server中一时表与表变量剖析

从底层原理到表层引用,书籍多的很。个人认为没有什么那本书好?这样的说法。主要看和个人的学习方法是否适合。

分手快乐 发表于 2015-1-18 18:26:01

个人感觉没有case直观。而且默认的第三字段(还可能更多)作为groupby字段很容易造成新手的错误。

简单生活 发表于 2015-1-27 16:18:19

如果处理少量数据,比如几百条记录的数据,我不知道这两种情况哪个效率更高,如果处理大量数据呢?比如有表中有20万条记录.

仓酷云 发表于 2015-2-5 14:26:10

可以动态传入参数,省却了动态SQL的拼写。

飘灵儿 发表于 2015-2-12 06:36:30

我们学到了什么?思考问题的时候从表的角度来思考问

小妖女 发表于 2015-3-3 00:10:42

个人感觉没有case直观。而且默认的第三字段(还可能更多)作为groupby字段很容易造成新手的错误。

爱飞 发表于 2015-3-11 08:48:26

还不是性能有问题!否则面向对象的数据库早就实现了!建议使用CLR的地方一般是和应用的复杂程度或操作系统环境有很高的耦合度的场景。如你想构建复杂的算法,并且用到了大量的指针和高级数据模型。

山那边是海 发表于 2015-3-18 08:06:29

SQLServer的异构移植功能个人感觉最好了。(如果对比过SQLServer的链接服务器和Oracle的透明网关的朋友会发现SQLServer的sp_addlinkedserver(openquery)异构数据库系列比Oracle真是强太多了。)

因胸联盟 发表于 2015-3-25 20:21:32

相信各位对数据库和怎么样学习数据库都有一些经验和看法,也会有人走了一些弯路总结出自己的经验来,希望大家能把各自的看法和经验拿出来分享,给别人一份帮助,给自己一份快乐
页: [1]
查看完整版本: Sql Server中一时表与表变量剖析