【讨论】写了个比较两条sql语句运行时间的存储过程,看大家有没有更好的方法或思路...

outwindows 2004-08-28 09:37:33
--由于要执行两条件sql语句才能测出它的执行时间,所以会产生很多次结果集
--能不能执行select 语句,但不产生结果集呢,或在最后得出结果之前清除之前产生的结果集

create proc dbo.PROC_SQL_COMP @sql1 varchar(8000),@sql2 varchar(8000),@t int
as
/*
调用:exec dbo.PROC_SQL_COMP @sql1='',@sql2='',@t=5
注:以下时间单位为ms(millisecond 毫秒)
比较两条件Sql语句执行时间,@sql1、@sql2为要比较的sql语句,@t为sql要运行的次数,结果为平均值
返回: AVG1 @sql1所用平均时间
AVG2 @sql2所用平均时间
DT1 @sql1所用总时间
DT2 @sql2所用总时间
TIMES 执行次数

*/
declare @dt1 datetime,
@dt2 datetime,
@dt3 datetime,
@dt4 datetime,
@ms1 bigint,
@ms2 bigint,
@i int

set @ms1 = 0
set @ms2 = 0
set @i = 0

--开始测试
while @i<@t
begin
set @dt1 = getdate()
exec(@sql1)
set @dt2 = getdate()

set @dt3 = getdate()
exec(@sql2)
set @dt4 = getdate()

set @ms1 = @ms1+datediff(ms,@dt1,@dt2)
set @ms2 = @ms2+datediff(ms,@dt3,@dt4)
set @i = @i+1
end
--结束

--测试结果
select AVG1=@ms1*1.00/@t,AVG2=@ms2*1.00/@t,TIMES=@t,DT1=@ms1,DT2=@ms2
...全文
342 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
abcdqq 2004-08-28
  • 打赏
  • 举报
回复
看不懂.
learning...
abcdqq 2004-08-28
  • 打赏
  • 举报
回复
调用外部程序?
zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
调用外部程序来解决吧
rea1gz 2004-08-28
  • 打赏
  • 举报
回复

futulove 2004-08-28
  • 打赏
  • 举报
回复
看不懂
outwindows 2004-08-28
  • 打赏
  • 举报
回复
想取平均值,因为在不同情况下sql语句执行时间可能会有一点点差别的,取平均值的话,得出的结果应该比较客观吧。
pbsql 2004-08-28
  • 打赏
  • 举报
回复
干嘛要循环呢?直接得出两SQL语句的单独执行时间然后比较就是了
zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
--冒牌的意思是这样分析吧?好像与楼主的要求有点不符合

SET SHOWPLAN_ALL on
go
select * from sysobjects
go
SET SHOWPLAN_ALL off
mql0000 2004-08-28
  • 打赏
  • 举报
回复
请问大家一个问题,我刚用SQL SERVER 不久,所以还不太懂,这个问题似乎有点太简单,可是我还是不太懂,请各位高手帮帮忙!
我的系统是2000的,只装了客户端组件,可是每次打开都启动不了,说是sql server不存在或访问被拒绝,在企业管理sql server组中新建注册也注册不了,服务器里好象没有可以选择的对象,包括本机也没有,我不知道该怎么办了,是不是要把本机设置为服务器呢?该怎么设置呢?请各位帮忙!!
outwindows 2004-08-28
  • 打赏
  • 举报
回复
SET SHOWPLAN_ALL 的设置是在执行或运行时设置,而不是在分析时设置。

当 SET SHOWPLAN_ALL 为 ON 时,SQL Server 返回每个语句的执行信息但不执行语句,而且 Transact-SQL 语句将不执行。将该选项设置为 ON 后,将返回有关所有后续 Transact-SQL 语句的信息,直到将该选项设置为 OFF 为止。例如,如果在 SET SHOWPLAN_ALL 为 ON 时执行 CREATE TABLE 语句,则 SQL Server 从涉及同一个表的后续 SELECT 语句返回错误信息;指定的表不存在。因此,对该表的后续引用将失败。当 SET SHOWPLAN_ALL 为 OFF 时,SQL Server 执行语句但不生成报表。
rea1gz 2004-08-28
  • 打赏
  • 举报
回复
我觉得不如研究清楚
SET SHOWPLAN_ALL ON
的返回结果,在两个sql语句前加SET SHOWPLAN_ALL ON,执行,对返回的信息进行统计,在比较,这样做比较合理些。

楼主原来的不处理的方法,主要是加入了大量的网络传输时间
邹建的方法变得很复杂,回滚事务的时间加入到测试的时间了,对某些语句可能很危险

outwindows 2004-08-28
  • 打赏
  • 举报
回复
不错,研究研究...
zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
大功告成,借用正式表,一次性调用osql来完成处理,这样就不存在增加附加时间的问题.
当然,要求调用者的权限是比较高的.


zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[PROC_SQL_COMP]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[PROC_SQL_COMP]
GO

/*--测试两组SQL的平均时间

利用osql.exe来测试两组 SQL 语句的执行时间
测试的存储过程中,调用了事务处理,所以如果测试的SQL语句有数据修改行为
会在调用结束后自动回滚事务,确保测试不会修改数据

已知的问题:
1.由于 osql 调用不允许使用多行,所以存储过程中会把回车换行替换成空格
对于 SQL 字符串中的回车换行,一样会被替换,所以对于字符串中包含回
车换行的 SQL 语句,可能会产生问题,除非回车换行不对 SQL 语句产生影响
2.由于是调用 xp_cmdshell 来执行 osql,所以要求有系统管理员的权限(比如sa)
3.调用 osql 使用了windows身份验证,这样省去了指定用户名及密码的麻烦
但如果你的 sql server 禁用了windows身份验证,则需要修改存储过程的 osql 调用

--邹建 2004.08(引用请保留此信息)--*/

/*--调用示例

exec dbo.PROC_SQL_COMP
'select top 1 * from sysobjects a,sysobjects b',
'select re=''1''
union all select 2'
--*/
create proc dbo.PROC_SQL_COMP
@sql1 varchar(7000), --测试的第一个sql语句
@sql2 varchar(7000), --测试的第二个sql语句
@t int=3 --测试次数
as
set nocount on
declare @s1 varchar(8000),@s2 varchar(8000),@tt varchar(20),@head varchar(8000)
declare @tb sysname
set @tb='tempdb.dbo.[temp_'+cast(newid() as varchar(36))+']'
exec('create table '+@tb+'(id int identity(0,1),m int)')

select @s1=replace(replace(@sql1,'''',''''''''''),char(13)+char(10),' ')
,@s2=replace(replace(@sql2,'''',''''''''''),char(13)+char(10),' ')
,@tt=cast(@t as varchar)
,@head='exec master..xp_cmdshell ''osql /E /d"'+db_name()+'"'
--使用了windows身份验证,如果不支持,则改 /E 为 /U"sa" /P"密码"
exec(@head+' /Q"set xact_abort on;declare @i int,@a datetime;set @i=0;while @i<'
+@tt+' begin select @i=@i+1,@a=getdate();begin tran;exec('''''+@s1
+''''');rollback tran;insert '+@tb+' select datediff(ms,@a,getdate());set @a=getdate();begin tran;exec('''''
+@s2+''''');rollback tran;insert '+@tb+' select datediff(ms,@a,getdate()) end"'',no_output')
exec('select 组号=''SQL''+cast(id%2+1 as varchar),平均时间=avg(m),总时间=sum(m),测试次数='+@tt+'
from '+@tb+' group by ''SQL''+cast(id%2+1 as varchar)
drop table '+@tb)
go
kekebear 2004-08-28
  • 打赏
  • 举报
回复
学习中。。。。。。。。
outwindows 2004-08-28
  • 打赏
  • 举报
回复
试试...
zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
用isql.exe的话,要求你的@sql1,@sql2语句不换行
zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
--用isql的话,你的存储过程可以修改如下(当然,明显是加长了执行时间的


--由于要执行两条件sql语句才能测出它的执行时间,所以会产生很多次结果集
--能不能执行select 语句,但不产生结果集呢,或在最后得出结果之前清除之前产生的结果集


create proc dbo.PROC_SQL_COMP @sql1 varchar(8000),@sql2 varchar(8000),@t int
as
/*
调用:
exec dbo.PROC_SQL_COMP @sql1='select * from sysobjects',@sql2='select a=''aa''',@t=5
注:以下时间单位为ms(millisecond 毫秒)
比较两条件Sql语句执行时间,@sql1、@sql2为要比较的sql语句,@t为sql要运行的次数,结果为平均值
返回: AVG1 @sql1所用平均时间
AVG2 @sql2所用平均时间
DT1 @sql1所用总时间
DT2 @sql2所用总时间
TIMES 执行次数

*/
declare @dt1 datetime,
@dt2 datetime,
@dt3 datetime,
@dt4 datetime,
@ms1 bigint,
@ms2 bigint,
@i int
declare @head varchar(8000)
set @head='exec master..xp_cmdshell ''isql /E /d"'+db_name()+'"'
set @ms1 = 0
set @ms2 = 0
set @i = 0

--开始测试
while @i<@t
begin
set @dt1 = getdate()
exec(@head+' /Q"'+@sql1+'"'',no_output')
-- exec(@sql1)
set @dt2 = getdate()

set @dt3 = getdate()
exec(@head+' /Q"'+@sql2+'"'',no_output')
-- exec(@sql2)
set @dt4 = getdate()

set @ms1 = @ms1+datediff(ms,@dt1,@dt2)
set @ms2 = @ms2+datediff(ms,@dt3,@dt4)
set @i = @i+1
end
--结束

--测试结果
select AVG1=@ms1*1.00/@t,AVG2=@ms2*1.00/@t,TIMES=@t,DT1=@ms1,DT2=@ms2

zjcxc 元老 2004-08-28
  • 打赏
  • 举报
回复
--当然可以啦.

--比如,执行你的@sql1
declare @head varchar(8000)
set @head='exec master..xp_cmdshell ''isql /E /d"'+db_name()+'"'
exec(@head+' /Q"'+@sql1+'"'',no_output')
outwindows 2004-08-28
  • 打赏
  • 举报
回复
查询语句里可调用isql?
加载更多回复(3)

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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