3

C# を使用してストアド プロシージャを呼び出そうとしています。ストアド プロシージャの実行時間は長く (3 ~ 4 分)、実行しようとするとタイムアウト例外が発生します。より長いタイムアウトで実行を終了させるにはどうすればよいですか?

また、例外がスローされた場合、ストアド プロシージャはサーバー上で実行を継続しますか、それとも停止しますか?

私のアプリケーションはゲーム サーバーであり、ストアド プロシージャを実行して mail を更新および削除します。SP の実行と同時にユーザーが別のレコードを挿入するには、レコードと接続が多すぎるため、実行が遅くなります。

SP を実行して、サーバーの応答を長時間待つだけです。

@minitech私の質問を編集してくれてありがとう

SPコードはこちら

ALTER    PROCEDURE [dbo].[SP_Mail_Scan]
 @NoticeUserID nvarchar(4000) output

AS  
Set @NoticeUserID=''
Declare @AuctionID Int        
Declare @AuctioneerID Int
Declare @AuctioneerName Nvarchar(100)
Declare @BuyerID Int
Declare @BuyerName Nvarchar(100)
Declare @ItemID Int
Declare @PayType Int
Declare @Price Int
Declare @Name Nvarchar(200)


Declare @MailID Int
Declare @SenderID Int
Declare @Sender Nvarchar(100)
Declare @ReceiverID Int
Declare @Receiver Nvarchar(100)
Declare @Title Nvarchar(1000)
Declare @Content Nvarchar(4000)
Declare @SendTime DateTime
Declare @IsRead Bit
Declare @IsDelR Bit
Declare @IfDelS Bit
Declare @IsDelete Bit
Declare @Annex1 Nvarchar(100)
Declare @Annex2 Nvarchar(100)
Declare @Gold Int
Declare @Money Int
Declare @Remark Nvarchar(200)
Declare @Annex3 Nvarchar(100)
Declare @Annex4 Nvarchar(100)
Declare @Annex5 Nvarchar(100)


Set @SenderID =0
Set @Sender =dbo.GetTranslation('SP_Mail_Scan.Sender')  --
Set @ReceiverID = ''
Set @Receiver = ''
Set @Title =dbo.GetTranslation('SP_Mail_Scan.Title')
Set @Content =dbo.GetTranslation('SP_Mail_Scan.Content')
Set @SendTime  = getdate()
Set @IsRead  = 0
Set @IsDelR = 0
Set @IfDelS = 0
Set @IsDelete =0
Set @Annex1 =''
Set @Annex2 =''
Set @Gold =0
Set @Money =0
Set @Annex3 =''
Set @Annex4 =''
Set @Annex5 =''

If object_id('tempdb..#PayMail') Is Not null
Drop Table #PayMail 

Create Table #PayMail 
(
id Int Identity(1,1), 
MailID Int Not Null,
SenderID Int Not Null,
Sender Nvarchar(200) Not null,
ReceiverID Int not null,
Receiver Nvarchar(200) not null,
Title Nvarchar(1000) not null,
Annex1 Nvarchar(100) not null,
Annex2 Nvarchar(100) not null,
Annex3 Nvarchar(100) not null,
Annex4 Nvarchar(100) not null,
Annex5 Nvarchar(100) not null,
) 

insert into #PayMail select [ID],SenderID,Sender,ReceiverID,Receiver,Title,isnull(Annex1,''),isnull(Annex2,''),isnull(Annex3,''),isnull(Annex4,''),isnull(Annex5,'') from User_Messages with(nolock) 
where IsExist=1 and Type>100 and datediff(hh,SendTime,getdate())>ValidDate and [Money]>0

  declare @NewTitle nvarchar(200)
  declare @NewContent nvarchar(200)
  set @NewTitle = dbo.GetTranslation('SP_Mail_Scan.Msg1')
  set @NewContent =dbo.GetTranslation('SP_Mail_Scan.Msg2')

set xact_abort on 
  begin tran

INSERT INTO User_Messages( SenderID, Sender, ReceiverID, Receiver, Title, Content, SendTime, IsRead, IsDelR, IfDelS, IsDelete, Annex1, Annex2, Gold, Money, IsExist,Type,Remark, Annex3, Annex4, Annex5) 
      select ReceiverID,Receiver,SenderID,Sender,@NewTitle+Title,REPLACE(@NewContent,'{0}',Receiver),getdate(), 0, 0, 0, 0,Annex1,Annex2,0,0,1,7,'Gold:0,Money:0,Annex1:'+Annex1+',Annex2:'+Annex2+',Annex3:'+Annex3+',Annex4:'+Annex4+',Annex5:'+Annex5,Annex3,Annex4,Annex5
    from #PayMail

  if @@error<>0 or @@ROWCOUNT =0
    begin
      rollback tran
      return 1 
   end

  update User_Messages set IsExist=0,@NoticeUserID = @NoticeUserID + cast(SenderID as nvarchar(50)) + ',' from User_Messages where [ID] in (select MailID from #PayMail)

  if @@error<>0 or @@ROWCOUNT =0
    begin
      rollback tran
      return 1 
   end

  commit tran
set xact_abort off

if len(@NoticeUserID)>0
begin
 set @NoticeUserID = substring(@NoticeUserID,1,len(@NoticeUserID)-1)
end
--set @NoticeUserID='100,200'

return 0
4

4 に答える 4

9

数百万の行と多数のテーブルを結合するデータベースであっても、正しい方法で設計してクエリを実行すれば、数秒で結果を返すことができます。

sproc と Explain Plan に時間をかけて、時間がかかる理由を理解する必要があります。データのセグメンテーション、クエリの個別のチャンクへの分割、インデックス、結合の構築方法、サブセレクトなどを検討してください。Explain Plan は、時間を無駄にしている場所を示します。

ストアド プロシージャの実行に 4 分もかからないようにする必要があります。特に、何らかのクライアント アプリケーションで実行している場合はそうです。

実行に 52 分かかっていた従来のクエリがありました。小さなリファクタリングでは 40 秒でした。その後、もう少しで 6 秒かかりました。40秒でも本当に押しています。

このような大規模なクエリがあり、それがレポート ベースである場合は、これらの目的により適したスキーマ設計を特徴とするデータ ウェアハウスを検討してください。

于 2012-06-09T00:02:42.697 に答える
8

ADO.NET SqlCommand を使用していると思いますか?

SqlCommand.CommandTimeout は、必要なタイムアウトを設定します

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout(v=vs.80).aspx

ストアド プロシージャは、クライアントがタイムアウトになるとすぐに停止します。

于 2012-06-09T00:01:37.523 に答える
3

Asynchronous Procedure Executionを使用できます。これは、クライアントが完了するのを待たずに手順を実行するための信頼できる方法です。

ただし、説明したような手順 (定期的に実行してメールをスキャンする必要があります) は仕事である可能性が高く、 SQL エージェントの方が適しています。

于 2012-06-09T06:02:44.453 に答える
-1

サンプルコードに従って、各変数に「Declare」を使用しています。変数ごとに単一の Declare を使用しないのはなぜですか。このような

Declare  @AuctionID Int        
        ,@AuctioneerID Int
        ,@AuctioneerName Nvarchar(100)
        ,@BuyerID Int
        ,@BuyerName Nvarchar(100)
        ,@ItemID Int
        ,@PayType Int
        ,@Price Int
        ,@Name Nvarchar(200)

        ,@MailID Int
        ,@SenderID Int
        ,@Sender Nvarchar(100)
        ,@ReceiverID Int
        ,@Receiver Nvarchar(100)
        ,@Title Nvarchar(1000)
        ,@Content Nvarchar(4000)
        ,@SendTime DateTime
        ,@IsRead Bit
        ,@IsDelR Bit
        ,@IfDelS Bit
        ,@IsDelete Bit
        ,@Annex1 Nvarchar(100)
        ,@Annex2 Nvarchar(100)
        ,@Gold Int
        ,@Money Int
        ,@Remark Nvarchar(200)
        ,@Annex3 Nvarchar(100)
        ,@Annex4 Nvarchar(100)
        ,@Annex5 Nvarchar(100)

このように、変数ごとに「設定」の代わりに単一の「選択」を使用しないのはなぜですか

Select   @SenderID =0
        ,@Sender = dbo.GetTranslation('SP_Mail_Scan.Sender')  --
        ,@ReceiverID = ''
        ,@Receiver = ''
        ,@Title = dbo.GetTranslation('SP_Mail_Scan.Title')
        ,@Content = dbo.GetTranslation('SP_Mail_Scan.Content')
        ,@SendTime  = getdate()
        ,@IsRead  = 0
        ,@IsDelR = 0
        ,@IfDelS = 0
        ,@IsDelete =0
        ,@Annex1 =''
        ,@Annex2 =''
        ,@Gold =0
        ,@Money =0
        ,@Annex3 =''
        ,@Annex4 =''
        ,@Annex5 =''

挿入操作用に #table を作成しましたが、そのテーブルのキーを指定していません。主キーを定義することをお勧めします

Create Table #PayMail 
(
     id Int Identity(1,1) Primary Key
    ,MailID Int Not Null
    ,SenderID Int Not Null
    ,Sender Nvarchar(200) Not null
    ,ReceiverID Int not null
    ,Receiver Nvarchar(200) not null
    ,Title Nvarchar(1000) not null
    ,Annex1 Nvarchar(100) not null
    ,Annex2 Nvarchar(100) not null
    ,Annex3 Nvarchar(100) not null
    ,Annex4 Nvarchar(100) not null
    ,Annex5 Nvarchar(100) not null
)

また、#table に挿入するときに "with (Nolock)" を使用したため、#table から選択するときにも with (Nolock) を使用する必要があります。#table が挿入に 1 回だけ使用される場合は、CTE (Common Table Expression) を同じように使用することをお勧めします。これにより、SP のパフォーマンスが向上する可能性があります。

于 2015-06-17T05:08:20.867 に答える