两语句性能对比

skyzcl 2008-06-24 11:44:43
语句一

DECLARE @depot nvarchar(10)
SELECT @depot='00000'
WHILE 1=1
BEGIN
SELECT @depot =depot FROM s_depot WHERE depot > @depot ORDER BY depot desc
IF @@rowcount <1
BREAK
PRINT @depot
END


语句二
DECLARE @depot nvarchar(10)
DECLARE cur1 CURSOR FOR SELECT depot FROM s_depot ORDER BY depot
OPEN cur1
FETCH next FROM cur1 INTO @depot
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @depot

FETCH next FROM cur1 INTO @depot
END
CLOSE cur1
DEALLOCATE cur1
...全文
152 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhiguo2008 2008-07-04
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 perfectaction 的回复:]
引用 13 楼 skyzcl 的回复:
引用 11 楼 perfectaction 的回复:
原则是能不使用游标就尽量别使用,看是否有变通的方式。

象此类查询,应如何变通呢?有没有更有效率的方法


大多是去变通业务了
[/Quote]
nzperfect 2008-06-24
  • 打赏
  • 举报
回复
[Quote=引用楼主 skyzcl 的帖子:]
语句一
SQL codeDECLARE@depotnvarchar(10)SELECT@depot='00000'WHILE1=1BEGINSELECT@depot=depotFROMs_depotWHEREdepot>@depotORDERBYdepotdescIF@@rowcount<1BREAKPRINT@depotEND

语句二
SQL codeDECLARE@depotnvarchar(10)DECLAREcur1CURSORFORSELECTdepotFROMs_depotORDERBYdepotOPENcur1FETCHnextFROMcur1INTO@depotWHILE@@FETCH_STATUS=0BEGINPRINT@depotFETCHnextFROMcur1INTO@depotENDCLOSEcur1DEALLOCATEcur1
[/Quote]

一般数据比较多情况下,仅这两个比较的话,第二个效率要高。
如果几行数据,就不明显了。
原因:
第一个是需要不停的到表里读取数据,不停的读io(或是内存缓存数据),造成大量的io读取,而io操作,是最慢最耗资源的。
第二个是一次性写入游标里,然后进行操作,读到的io相对的第一种是极小的,而游标效率也并非是极差,不然,ms也就不用它了。
yinqi025 2008-06-24
  • 打赏
  • 举报
回复
这个是没咋可比性...
yinqi025 2008-06-24
  • 打赏
  • 举报
回复
第一个应该快很多
Garnett_KG 2008-06-24
  • 打赏
  • 举报
回复
毫无可比性
两条语句的得出来的结果可能都不一样

datahandler2 2008-06-24
  • 打赏
  • 举报
回复
我感觉估计第一个会比较高点。第二个用到游标相当资源比较耗
nzperfect 2008-06-24
  • 打赏
  • 举报
回复
楼主测试的结果呢,说说吧
skyzcl 2008-06-24
  • 打赏
  • 举报
回复
哪个效率高呢?一直很困惑
nzperfect 2008-06-24
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 skyzcl 的回复:]
引用 11 楼 perfectaction 的回复:
原则是能不使用游标就尽量别使用,看是否有变通的方式。

象此类查询,应如何变通呢?有没有更有效率的方法
[/Quote]

大多是去变通业务了
yinqi025 2008-06-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 perfectaction 的回复:]
我上面在7楼说的不对,通过测试,发现游标也是需要一次一次的去查里查数据,更正并测试下:


SQL code--生成测试表,10000条数据
create table t_test(id int identity(1,1) primary key,class_a varchar(50),class_b varchar(50),add_dt datetime)
go
declare @i int
select @i = 1
while @i < = 10000
begin
insert into t_test(class_a,class_b,add_dt)
select case @i%2 when 0 then 'class_a' + …
[/Quote]

那我错了...我以为游标很影响速度,帮助很大对我...up
skyzcl 2008-06-24
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 perfectaction 的回复:]
原则是能不使用游标就尽量别使用,看是否有变通的方式。
[/Quote]
象此类查询,应如何变通呢?有没有更有效率的方法
nzperfect 2008-06-24
  • 打赏
  • 举报
回复
可以把数据插入到一个@t table变理中,这个@t table设置一个自增长列
去循环这个内存表,在你服务器内存足够大时,或许性能好于游标。
nzperfect 2008-06-24
  • 打赏
  • 举报
回复
原则是能不使用游标就尽量别使用,看是否有变通的方式。
skyzcl 2008-06-24
  • 打赏
  • 举报
回复
象此类查询,有没有比游标更有效率的方法呢?请教
skyzcl 2008-06-24
  • 打赏
  • 举报
回复
原来原理是这样啊,一直以为游标慢,看来还是有适用的地方!谢谢LS的
nzperfect 2008-06-24
  • 打赏
  • 举报
回复
我上面在7楼说的不对,通过测试,发现游标也是需要一次一次的去查里查数据,更正并测试下:

--生成测试表,10000条数据
create table t_test(id int identity(1,1) primary key,class_a varchar(50),class_b varchar(50),add_dt datetime)
go
declare @i int
select @i = 1
while @i < = 10000
begin
insert into t_test(class_a,class_b,add_dt)
select case @i%2 when 0 then 'class_a' + cast(@i as varchar) else cast(@i as varchar) end,
case @i%5 when 0 then 'class_b' + cast(@i as varchar) else cast(@i as varchar) end, getdate()
select @i = @i + 1
end


--测试第一种所需时间
declare @t1 datetime,@t2 datetime
declare @a int,@b int
select @t1 = getdate()
declare @depot nvarchar(10)
select @depot='2'
while 1=1
begin
select @depot =id from t_test where id > @depot order by id desc
if @@rowcount <1
break
print @depot
end
select @t2 = getdate()
select cast(datediff(ms,@t1,@t2) as varchar)+'ms'
--结果:
30983ms


--测试第二种:
declare @t1 datetime,@t2 datetime
declare @a int,@b int
select @t1 = getdate()
declare @depot nvarchar(10)
declare cur1 cursor for select id from t_test where id between 3 and 10000 order by id
open cur1
fetch next from cur1 into @depot
while @@fetch_status = 0
begin
print @depot

fetch next from cur1 into @depot
end
close cur1
deallocate cur1
select @t2 = getdate()
select cast(datediff(ms,@t1,@t2) as varchar)+'ms'
--结果:
623ms


通过查看io读:
set statistics io on

发现这两个的区别在于:
第一个查询执行时是:select id from t_test where id > 30 order by id desc
而第二个查询是直接取某一行:select id from t_test where id = 30

也就是说楼主的:
SELECT @depot =depot FROM s_depot WHERE depot > @depot ORDER BY depot desc

在while时,每次要读取depot > @depot的所有数据页,而游标的则只读取一条记录的数据页。

22,207

社区成员

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

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