2

私にはトリガーがありますAfter Update

このトリガーは、リンク サーバー上の 2 つのテーブルを更新しようとしているサーバー上で機能します。

コードを見る

ALTER TRIGGER [dbo].[tgAfterUpdate] ON  [dbo].[KS_3EToVision]
   AFTER UPDATE
AS 
BEGIN

  BEGIN TRY
  BEGIN TRANSACTION    -- Start the transaction

  DECLARE @MatterNumber varchar(15);
  SELECT @MatterNumber = i.MatterNumber FROM inserted i; 

    IF EXISTS(SELECT * FROM [FSSQLDEV01].[collnab].[dbo].[collection_header] WHERE         Ch_file_number COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT)
       --UPDATE
        IF (SELECT Ch_matter_status FROM [FSSQLDEV01].[collnab].[dbo].[collection_header] WHERE Ch_file_number COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT ) = 'Current'
             BEGIN 
                --Parent table 
                UPDATE [FSSQLDEV01].[collnab].[dbo].[collection_header]
                SET 
                    Ch_start_date = i.OpenDate 
                FROM 
                    Inserted i 
                WHERE ch_file_number COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT  

                ----Child table 
                UPDATE [FSSQLDEV01].[collnab].[dbo].[collections] 
                SET 
                    Defendant_1 = i.Description 
                    , Loan_Number_1 = i.Comments 
                    , Client = i.KS_BookName 
                    , Date_Instructed = i.OpenDate 
                    , Person_Responsible_name = i.ResponsibleFeeEarnerName 
                    , Person_Responsible_Email = i.ResponsibleFeeEarnerEmail 
                    , Person_Acting_name = i.BillingFeeEarnerName 
                    , Person_Acting_email = i.BillingFeeEarnerEmail 
                    , Agent_Acting_name = i.BillingFeeEarnerName 
                    , Agent_Acting_email = i.BillingFeeEarnerEmail 
                    , CBA_Panel_Service_Area = i.KS_ServiceCat 
                    , HBN_Number = i.KS_ClientAcctRef 
                    , St_George_Contact = i.KS_Instructor 
                FROM 
                    Inserted i 
                WHERE Left(Collections.file_number,6) COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT
             END

--If we reach here, success!
   COMMIT
END TRY
BEGIN CATCH
  -- Whoops, there was an error
  IF @@TRANCOUNT > 0
     ROLLBACK

  -- Raise an error with the details of the exception
  DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
  SELECT @ErrMsg = ERROR_MESSAGE(),
     @ErrSeverity = ERROR_SEVERITY()

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH

END 

トリガーの外側で同じ基準を使用して更新ステートメントを試行すると、1 秒しかかかりませんが、トリガーの内側では最大 45 秒かかる場合があります。

2番目の更新ステートメントを削除するとすぐに実行されるため、問題となっている2番目の更新ステートメントに絞り込みました。

ショーの画像も添付しました

また、挿入用のトリガーもあり、これは1秒以内にすばやく機能し、削除用のトリガーはトリガー内で長時間かかりますが、トリガーの外側にある2つの削除ステートメントを削除すると正常に機能します。

USE [TE_3E_TRG]
GO
/****** Object:  Trigger [dbo].[tgAfterDelete]    Script Date: 08/30/2012 11:24:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[tgAfterDelete] ON  [dbo].[KS_3EToVision]
   AFTER DELETE
AS 

begin

BEGIN TRY
   BEGIN TRANSACTION    -- Start the transaction
            Begin
                --Parent table 
                DELETE FROM [FSSQLDEV01].[collnab].[dbo].[collection_header] WHERE ch_file_number COLLATE DATABASE_DEFAULT = (SELECT d.MatterNumber FROM deleted  d) COLLATE DATABASE_DEFAULT

                --Child table 
                DELETE FROM [FSSQLDEV01].[collnab].[dbo].[collections] WHERE Left(file_number,6) COLLATE DATABASE_DEFAULT = (SELECT d.MatterNumber FROM deleted  d) COLLATE DATABASE_DEFAULT            

            END
   -- If we reach here, success!
   COMMIT
END TRY
BEGIN CATCH
  -- Whoops, there was an error
  IF @@TRANCOUNT > 0
     ROLLBACK

  -- Raise an error with the details of the exception
  DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
  SELECT @ErrMsg = ERROR_MESSAGE(),
         @ErrSeverity = ERROR_SEVERITY()

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH

トリガー内とトリガーの外側でステートメントを実行する間に、実行時間にこの劇的な違いが生じる理由を知っている人はいますか?

4

1 に答える 1

0

リモート テーブルをローカル仮想挿入テーブルと結合しています。これにはおそらく、テーブル全体をリモート サーバーからローカルにコピーし、ローカルでフィルタリングする必要があります。

これは、カーソルを使用して行ごとに更新するとおそらくパフォーマンスが向上する非常にまれなケースです。

ところで、marc_s のポイントは正しいです。挿入されたテーブルに複数の行がある可能性をコードで説明する必要があります。

于 2012-12-19T17:53:39.827 に答える