Insert Into ..Select.. 的执行逻辑顺序和效率讨论,来着有分。

香椿炒鸡蛋 2008-07-18 11:19:26
问题一: Insert Into table1 (select * from table2) 的具体执行顺序是怎么样的?

我的理解是先执行(select * from table2) 得到全部的结果集N1,然后将N1的数据插入到table1中,而不是:select一条数据接着insert该条数据。

问题二:为了达到Insert Into table1 (select * from table2) 语句的执行效果,我添加一个处理,看看效率会受到怎样的影响?

我要添加的处理是:先执行 (select * from table2)并将结果集存入到游标cursor中,然后将游标的数据按行取出存入临时变量中,接着将这些变量的值

通过insert语句插入到 table1中(使用游标fetch next 依次执行该插入操作)。


欢迎大家讨论。
...全文
2580 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
bwu851 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 chenjunsheep 的回复:]
先执行select * from table2,然后把结果一次性的写入table1中
[/Quote]
chenjunsheep 2008-07-18
  • 打赏
  • 举报
回复
先执行select * from table2,然后把结果一次性的写入table1中
Herb2 2008-07-18
  • 打赏
  • 举报
回复
这个有必要讨论吗?
从性能分析,DBMS肯定会有优化的,是一行一行插入还是一页一页插入似乎取决于DBMS的算法,怎么最优,不过可以肯定用游标一行一行的插入肯定是最差的。
从锁定分析,这个分析不来,但感觉不会锁定原表,目的表会被整表锁定(应该是根据记录的多少逐步升级锁。)
xiaoku 2008-07-18
  • 打赏
  • 举报
回复
有一个 HALLOWEEN 的过程...
香椿炒鸡蛋 2008-07-18
  • 打赏
  • 举报
回复
根据11楼的分析, 添加游标应该是多余的 。
Garnett_KG 2008-07-18
  • 打赏
  • 举报
回复
理论上讲不是先读完结果集(N),然后再Insert到目标table中,这个过程是连续的。

因为Table Scan并不是一个Stop-and-Go 的操作,它并不会引起封锁 。

试想一下,当系统中存在多个CPU而且Table数据量很大时,SQLServer一般都会

生成并行执行计划,如果要等所有的资料全部扫描完然后再做下一步操作,并行的目的那不是白搭了。


香椿炒鸡蛋 2008-07-18
  • 打赏
  • 举报
回复
我试验一下。。
lgxyz 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mugua604 的回复:]
问题一: Insert Into table1 (select * from table2) 的具体执行顺序是怎么样的?

我的理解是先执行(select * from table2) 得到全部的结果集N1,然后将N1的数据插入到table1中,而不是:select一条数据接着insert该条数据。
为什么不是呢?我理解就是。。。
[/Quote]
select一条数据接着insert该条数据
我是这么认为的
sdxiong 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 falconshh 的回复:]
关于问题二: 我的看法是,中间的游标处理是多余的,增加了系统的开销和负担,完全可以不要的。
[/Quote]

假设test表中有三条记录

insert into test select * from test 这样,触发器只触发一次
改成游标方法后,每插入一次则触发一次,也就是共触发三次
sdxiong 2008-07-18
  • 打赏
  • 举报
回复
很简单,建一个表TEST,随便添加几条数据,然后建一个触发器

ALTER TRIGGER [test_trigger]
ON [dbo].[Test]
AFTER INSERT,DELETE,UPDATe
AS
BEGIN
SET NOCOUNT ON;

declare @a varchar(100)
set @a='delete:' + convert(char(5),isnull((select count(*) from deleted ),0))
+ ' insert:' + convert(char(5),isnull((select count(*) from inserted),0))
raiserror(@a,16,1)
rollback

END


然后运行一下insert into test select * from test,看看错误信息就知道

lgxyz 2008-07-18
  • 打赏
  • 举报
回复
用游标就是多余的
香椿炒鸡蛋 2008-07-18
  • 打赏
  • 举报
回复
关于问题二: 我的看法是,中间的游标处理是多余的,增加了系统的开销和负担,完全可以不要的。
香椿炒鸡蛋 2008-07-18
  • 打赏
  • 举报
回复
大家意见一致啊,有做过这方面的验证的或者证据什么的没啊。。
sdxiong 2008-07-18
  • 打赏
  • 举报
回复
先执行select * from table2,然后把结果一次性的写入table1中
liangCK 2008-07-18
  • 打赏
  • 举报
回复
来者有分.
mugua604 2008-07-18
  • 打赏
  • 举报
回复
问题一: Insert Into table1 (select * from table2) 的具体执行顺序是怎么样的?

我的理解是先执行(select * from table2) 得到全部的结果集N1,然后将N1的数据插入到table1中,而不是:select一条数据接着insert该条数据。
为什么不是呢?我理解就是。。。
linguojin 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 hery2002 的回复:]
关于第一个问题,
应该是批量写入的,
DBMS也不至于这么低级吧,
按照每行逐次插入,
这样对于系统大批量的插入来说,
效率可想而知.
关于第二个问题,
游标在这里并没有起到很好的作用.
反而在启用游标的过程中会增加系统的资源占用.
[/Quote]
wwd252 2008-07-18
  • 打赏
  • 举报
回复
顶顶哦
香椿炒鸡蛋 2008-07-18
  • 打赏
  • 举报
回复
7楼,14楼,11楼都给了比较深入的思路
lff642 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 liangCK 的回复:]
来者有分.
[/Quote]
加载更多回复(1)

22,297

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧