使用显式create table语句与select into创建表

时间:2011-07-26 15:04:21

标签: sql sql-server database sql-server-2008

使用显式create table语句和加载数据与选择之间是否存在任何性能差异。此示例仅显示2列,但问题是面向使用非常大的表。下面的示例也使用临时表,但我想知道使用常规表时的效果。我认为无论桌子类型如何,它们都是一样的。

临时表方案:

--- Explicitly creating temp table first and then loading.
create table #test1 (id int, name varchar(100))
insert into #test1 (id, name) select id, name from #bigTable

--- Creating temp table by selecting into.
select id,name into #test2 from #bigTable

或常规表:

--- Explicitly creating table first and then loading.
create table test1 (id int, name varchar(100))
insert into test1 (id, name) select id, name from #bigTable

--- Creating table by selecting into.
select id,name into test2 from bigTable

每个人对此有何看法?我认为显式创建表和加载必须具有比选择select更好的性能必须在语句中评估表达式以创建表。

我们的组织通常明确地创建临时表作为标准实践,我们想知道一切都认为实际上是最佳实践。

http://msdn.microsoft.com/en-us/library/ms188029.aspx

3 个答案:

答案 0 :(得分:5)

CREATE TABLE可让您在插入数据之前更好地控制表格的定义,例如NOT NULL,约束等使用SELECT INTO无法完成的事情。

SELECT INTO是一种最低限度记录的操作,但在某些情况下,INSERT..SELECT也可以进行最低限度的记录。
请参阅The Data Loading Performance Guide,尤其是以下部分:总结最小日志记录条件

简单地说,如果您不关心约束等(例如,您想快速创建表的副本),SELECT..INTO恕我直言的优势是更短的代码。
否则,你应该使用另一种方式,你仍然可以将其记录得最少。

答案 1 :(得分:2)

选择进入具有日志记录优势(没有那么多),因此在大多数情况下性能实际上更好。但是,如果表存在,则会出错,并且不会构建索引或约束等内容,只会构建列。

取决于你需要它。我知道我们有一些SELECT ... INTO然后重命名的操作,因为它比更新旧表更快(显然有很多绒毛来重建表对象等)。

请记住,我们的用法不是临时表,我在你的问题中已经注意到了这一点。

对于带索引的表,insert into必须将索引作为插入过程的一部分进行维护。然后有其他表对象可以导致更多处理,例如触发器。在select into的情况下,就我所知,该表是简单的,因此初始插入性能非常好。加上事务日志影响很小(在你的问题的链接中提到这一点)。

这实际上取决于使用情况,对于临时表,我认为它们的寿命相对较短,因此select into后跟truncate / drop可以很好地工作。如果他们有更长的跨度,但是否则会被丢弃,再次选择进入,然后最终的下降可以工作。

如果他们需要在创建后长时间存活并且不会丢弃,那么除了最初创建和插入数据(这将是快速的)之外,您将在后续插入方面回到正方形 - 您最好只调整表以接受快速插入,例如通过使用最小索引或通过先禁用索引并重新启用后插入。

在大型表碰巧有聚簇索引的情况下,我还看到了一个技巧,其中插入的数据按插入的聚簇索引排序。

答案 2 :(得分:0)

在我的情况下,执行显式CREATE然后INSERT INTO在实际运行时间和优化器的估计成本方面表现明显更好。

我的临时表不大(8行),但其中一个值是计算的字符串值。在某些情况下,此临时表与具有数十万行的结果集连接在一起。我相信当我为临时表执行SELECT INTO时,它没有最佳地为计算值选择数据类型。因此,当我使用CREATE显式定义列数据类型时,SQL Server能够更有效地执行连接。当然,这种影响被夸大了,因为涉及了很多行。

因此,在某些情况下,特别是当您的某个列是计算值时,CREATE和INSERT可能是更好的选择。你的里程可能会有所不同,所以一定要进行一些测试!