简体   繁体   English

SQL存储过程超时

[英]SQL Stored Proc Time out

I have a stored procedure which is timing out when called thru a .net windows service. 我有一个存储过程,当通过.net Windows服务调用时会超时。

Error: Execution Timeout Expired. 错误:执行超时已过期。
The timeout period elapsed prior to completion of the operation or the server is not responding. 在操作完成之前超时或服务器没有响应。

The wait operation timed out 等待操作超时

@fetchbatchsize gets the value from ctp_config which is '2500' and uses that value to select top 2500 records from another table ctp_otran. @fetchbatchsize从ctp_config获取值为“ 2500”,并使用该值从另一个表ctp_otran中选择前2500条记录。 approx records in ctp_otran is 23102025. ctp_otran中的大约记录为23102025。

The same stored proc works good with '1000' records without giving any timeout issues. 相同的存储过程可以很好地处理'1000'记录,而不会出现任何超时问题。

Following is the stored proc. 以下是存储的过程。

ALTER PROCEDURE [dbo].[sp_ctp_get_otran]
@feed varchar(20)
AS
BEGIN
SET NOCOUNT ON;

DECLARE @fetchbatchsize char(25),
        @parameter varchar(50) = 'otran_default_batch_size_'
        ,@dync_exec nvarchar(MAX)

set @fetchbatchsize = (select value from [dbo].[ctp_config] where parameter = 
@parameter+@feed)

If(@fetchbatchsize is null)
set @fetchbatchsize = '1000'

select top (0) ctp_otran.otran_id, ctp_otran.unq_number as unq_number,  
   ctp_otran.entity, ctp_otran.field, 
   ctp_otran.str_value, ctp_otran.dec_value, ctp_otran.dtm_value, 
ctp_otran.proc_status 
into #otran
from ctp_otran with (nolock) 

select @dync_exec = 'INSERT INTO #otran (
otran_id,
unq_number,
entity,
field,
str_value,
dec_value,dtm_value,proc_status
)
select top (cast(' +@fetchbatchsize+ ' as int)) ctp_otran.otran_id, 
ctp_otran.unq_number as unq_number, 
ctp_otran.entity, ctp_otran.field, 
ctp_otran.str_value, ctp_otran.dec_value, ctp_otran.dtm_value, 
ctp_otran.proc_status 


from ctp_otran with (nolock) 
where ctp_otran.feed = '''+@feed + '''
and ctp_otran.proc_status = 0 
order by entity, unq_number, field;'


EXEC (@dync_exec)

update ctp_otran 
set proc_status = 3 -- in process 
where otran_id in (select otran_id from #otran);


select otran_id, unq_number, entity, field, str_value, dec_value, dtm_value, 
proc_status 
from #otran; 

drop table #otran;

END

Assuming you're on SQL 2005 or later (and you really should be), you can replace the dynamic SQL with this: 假设您使用的是SQL 2005或更高版本( 确实如此),则可以用以下方式替换动态SQL:

INSERT INTO #otran (
    otran_id,
    unq_number,
    entity,
    field,
    str_value,
    dec_value,dtm_value,proc_status
)
select top (@fetchbatchsize) 
    ctp_otran.otran_id, 
    ctp_otran.unq_number as unq_number, 
    ctp_otran.entity, ctp_otran.field, 
    ctp_otran.str_value, ctp_otran.dec_value, ctp_otran.dtm_value, 
    ctp_otran.proc_status 
from ctp_otran with (nolock) 
where ctp_otran.feed = @feed 
and ctp_otran.proc_status = 0 
order by entity, unq_number, field;

@fetchbatchsize will need to be stored as an Int rather than a Varchar, of course. 当然,@ fetchbatchsize将需要存储为Int而不是Varchar。

Finally, you don't need to explicitly drop your temp table(s). 最后,您无需显式删除临时表。 They vanish when the stored procedure ends. 当存储过程结束时,它们消失。

I think you could replace the whole logic with this: 我认为您可以将整个逻辑替换为:

select @fetchbatchsize = value 
from dbo.ctp_config 
where parameter = @parameter+@feed

update o 
set proc_status = 3 -- in process 
from (
    select top @fetchbatchsize *
    from ctp_otran
    where ctp_otran.feed = @feed
    and ctp_otran.proc_status = 0 
    order by entity, unq_number, field
) o
output inserted.otran_id, inserted.unq_number, inserted.entity, inserted.field, inserted.str_value, inserted.dec_value, inserted.dtm_value, inserted.proc_status 

Didn't test this but don't see why it wouldn't work. 没测试过,但看不到为什么不起作用。 If the derived table doesn't work CTE should at least. 如果派生表不起作用,则CTE至少应如此。

If you have more than 1 process doing this same handling in the table at the same time, your code ends up in both race conditions where same ids are selected multiple times and to deadlocks in the database (which is probably why you added nolock) 如果您有多个进程同时在表中进行相同的处理,则代码将同时处于两种竞态条件,在这种竞态条件中,多次选择了相同的ID并导致数据库死锁(这可能是您添加nolock的原因)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM