仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 897|回复: 7
打印 上一主题 下一主题

[学习教程] CTE,一时表,表变量区分跟详细合用场景剖析

[复制链接]
只想知道 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 14:07:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
提供多语言支持,常见的编码如中文的GB2312、BIG5,日文的Shift_JIS等都可以用作数据表名和数据列名。在这之前我们先懂得CTE,一时表,表变量的基础观点
1、一时表:一时表有两品种型:当地表和全局表。在与初次创立或援用表时不异的SQLServer实例毗连时代,当地一时表只关于创立者是可见的。当用户与SQLServer实例断开毗连后,将删除当地一时表。全局一时表在创立后对任何用户和任何毗连都是可见的,当援用该表的一切用户都与SQLServer实例断开毗连后,将删除全局一时表。

2、CTE:CTE(CommonTableExpression),即公用表表达式,能够以为是在单个SELECT、INSERT、UPDATE、DELETE或CREATEⅥEW语句的实行局限内界说的一时了局集。CTE与派生表相似,详细体现在不存储为工具,而且只在查询时代无效。与派生表的分歧的地方在于,CTE可自援用,还可在统一查询中援用屡次。

3、表变量:说白了和表没甚么区分,只不外是以变量的情势存在,你像会见一般的表一样往会见,往做增编削查的操纵。最主要的是为何有了一时表,还要全部表变量呢,存期近公道,表变量的确有其长处,比方它不必要在存储历程停止的时分开释(DROP),招致存储历程编译更少等等。

CTE绝对对照复杂一点,
非递回的CTE从物理来讲,有点相似一般的视图的观点,在编译的时分优化器会把它扩大开来。好比上面的,QO会把1转化为2
1,WITHO_CTE([name],[object_id])
AS
(SELECT[name],[object_id]FROM[sys].[all_objects])
SELECTtop11O.[name],O.[object_id]
FROMO_CTEOINNERJOIN[sys].[all_columns]CONO.[object_id]=C.[object_id];
GO

--transformation
2,SELECTtop11O.[name],O.[object_id]
FROM(SELECT[name],[object_id]FROM[sys].[all_objects])OINNERJOIN[sys].[all_columns]CONO.[object_id]=C.[object_id];
GO

表变量与一时表很庞大,以是曲解相称的多,起首说一下相干的曲解的器材。

1),存储地位.
一句话:表变量与一时表在存储地位上没有实质区分。

2,表变量与一时表跟tempdb干系。
表变量与一时表在tempdb实例化,而且最后在BPOOL中发生,而且在checkpoint产生之前,它们就已存在于tempdb中了,固然它还没有刷进磁盘,可是它们就已属于而且存在于tempdb中了。固然在checkpoint后生以后,BPOOL中的数据被输出磁盘,可是不论有无产生checkpoint,数占有没有被输出磁盘,换句话说,不管表变量与一时表只存是在BPOOL中,仍是同时存在于BPOOL与磁盘(manualcheckpoint),大概只存在于磁盘(lazywriter后),表变量与一时表都存在于tempdb中。

下面的形貌一样合用于用户数据库中的用户表,就仿佛是在用户数据库USERDB顶用户表usertable天生1000笔记录,那它一定是起首在BPOOL中天生的,可是在checkpoint之前,它也是不会被刷进磁盘的,那这个1000笔记录属于数据库USERDB吗?固然拉。

3,表变量不介入事物吗?那为何还要发生日记呢?
表变量并不是不介入事物,而不介入用户事物,体系事物仍是介入的,以是会发生日记。

4),表变量不介入锁机制吗?
表变量固然会介入锁机制。
DBCCTRACEOFF(1200,-1)
GO
DECLARE@TVTABLE(CLint)
DBCCTRACEON(1200,-1,3604)
INSERTINTO@TV(CL)VALUES(1)
DBCCTRACEOFF(1200,-1)
GO

5,表变量会不会重编译,而一时表会重编译吗?
固然不是,一时表的重编译是必要前提的。
好比上面的,你实行屡次Proc1,可是你只会看到一次的SP:Recompile,这措辞,一时表的企图被重用了。
createprocedureProc1
as
begin
createtable#t1(aint,bint);
insertinto#t1values(1,2);
select*from#t1;
end

execProc1

再没有到达某些限制的阀值之前,是不必要重编译的,详细公式以下。
Ifn<6,Recompilationthreshold=6.
If6<=n<=500,Recompilationthreshold=500.
Ifn>500,Recompilationthreshold=500+0.20*n.

别的在实行企图中,EstimatedRowcount是一个十分主要的器材,由于它间接决意了实行企图的选择,上面来问人人一些成绩,前面会有成绩的谜底,人人能够先想一想再看谜底。

----------------------------------------------------------------------------------------
成绩
----------------------------------------------------------------------------------------
先创立表并拔出数据
SETNOCOUNTON;

DECLARE@tbTABLE(
[C1][nvarchar](50)NOTNULL,
[C2][date]NOTNULL,
[C3][nchar](1)NOTNULL,
[C4]bitNULL,
[C5]bitNOTNULL);

INSERTINTO@tb
SELECT1,getdate(),1,1,1

--天生1024条测试纪录
declare@iint
set@i=0
while@i<10
begin
INSERTINTO@tb
SELECT*from@tb
set@i=@i+1
end

SETSTATISTICSPROFILEON;
SELECT*from@tb
--1.EstimatedRowcount为1,这个很分明。
SELECT*from@tbOPTION(RECOMPILE)
--为何EstimatedRowcount为1024?

SELECT*from@tbwhere[C1]like1OPTION(RECOMPILE)
--为何EstimatedRowcount为102.4?

SELECT*from@tbwhere[C1]Notlike1OPTION(RECOMPILE)
--为何EstimatedRowcount为921.6?

SELECT*from@tbwhere[C1]between1and2OPTION(RECOMPILE)
--为何EstimatedRowcount为92.16?

SELECT*from@tbwhere[C1]notbetween1and2OPTION(RECOMPILE)
--为何EstimatedRowcount为522.24?

SELECT*from@tbwhere[C4]=1OPTION(RECOMPILE)
--为何EstimatedRowcount为337.92?

SELECT*from@tbwhere[C5]=1OPTION(RECOMPILE)
--为何EstimatedRowcount为512?

SELECT*from@tbwhere[C2]<getdate()OPTION(RECOMPILE)
--为何EstimatedRowcount为307.2?

SETSTATISTICSPROFILEOFF;

----------------------------------------------------------------------------------------
谜底
----------------------------------------------------------------------------------------
RECOMPILE使得@tb在运转insertinto以后从头评价@tb的行数,由于这个时分已insert终了,以是能正确的失掉它的行数。
由于统共拔出了1024行,以是@tb的totalcount为1024"。

SELECT*from@tbOPTION(RECOMPILE)
--为何EstimatedRowcount为1024?
由于统共就拔出了1024行,拔出以后再次评价它的行数,就可以得它对照正确的值。

SELECT*from@tbwhere[C1]like1OPTION(RECOMPILE)
--为何EstimatedRowcount为102.4?
关于不含混的like,EstimatedRowcount=totalcount*10%=1024*10%=102.4

EstimatedRowcountSELECT*from@tbwhere[C1]Notlike1OPTION(RECOMPILE)
--为何EstimatedRowcount为921.6?
Notlike的EstimatedRowcount=totalcount-likeEstimatedRowcount=1024-102.4=921.6

SELECT*from@tbwhere[C1]between1and2OPTION(RECOMPILE)
--为何EstimatedRowcount为92.16?
关于between的EstimatedRowcount=totalcount*9%=1024*9%=92.16

SELECT*from@tbwhere[C1]notbetween1and2OPTION(RECOMPILE)
--为何EstimatedRowcount为522.24?
notbetween的EstimatedRowcount为totalcount*51%=522.24

SELECT*from@tbwhere[C5]=1OPTION(RECOMPILE)
--为何EstimatedRowcount为512?
[C5]的范例为bitNOTNULL,以是有2种值,以是EstimatedRowcount=totalcount*1/2=512

SELECT*from@tbwhere[C4]=1OPTION(RECOMPILE)
--为何EstimatedRowcount为337.92?
[C4]的范例为bitNULL,以是有3种值的大概,以是EstimatedRowcount=totalcount*1/3=337.92

SELECT*from@tbwhere[C2]<getdate()OPTION(RECOMPILE)
--为何EstimatedRowcount为307.2?
一样平常关于>大概<EstimatedRowcount为EstimatedRowcount*30%=307.2这类操作的执行过程是,1)按照新的表定义建立一个临时表tmpa,2)将原表数据拷贝到临时表,3)将原始表改名tmpb,4)将tmpa改名为原表名,5)将tmpb删除。
透明 该用户已被删除
沙发
发表于 2015-1-18 11:59:40 | 只看该作者
where子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。
莫相离 该用户已被删除
板凳
发表于 2015-1-26 14:49:44 | 只看该作者
财务软件要用SQL也只是后台的数据库而已,软件都是成品的,当然多学东西肯定是有好处的..
活着的死人 该用户已被删除
地板
发表于 2015-2-4 20:24:18 | 只看该作者
SQL语言是学习所有数据库产品的基础,无论你是做数据库管理还是做数据库开发都是这样。不过具体学习的侧重点要看你将来做哪一块,如果是做数据库管理(DBA),侧重点应该放在SQLServer的系统管理上.
简单生活 该用户已被删除
5#
发表于 2015-2-10 07:01:33 | 只看该作者
每天坚持做不一样的是,认真做笔录,定时复习。一个月你就可以有一定的收获。当然如果你想在sql方面有一定的造诣,你少不了需要看很多很多的书籍了。
再现理想 该用户已被删除
6#
发表于 2015-3-1 03:35:19 | 只看该作者
只能告诉你,学好数据库语言和原理,多见识几种数据库软件,比一棵树上吊死要好。
因胸联盟 该用户已被删除
7#
发表于 2015-3-10 12:46:41 | 只看该作者
现在是在考虑:如果写到服务器端,我一下搞他个10个存储过程导过去,那久之服务器不就成垃圾箱了吗?即便优化了我的中间层.
第二个灵魂 该用户已被删除
8#
发表于 2015-3-24 02:42:59 | 只看该作者
是否碎片会引发效率问题?这都是需要进一步探讨的东西。varbinary(max)代替image也让SQLServer的字段类型更加简洁统一。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-22 19:49

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表