私は現在、以下の2つの表1と表2の構造を持っています。あなたが見ることができるように表1は、列FKのために複数の行が含まれており、FKの列には、表1SQLカーソルのパフォーマンス/代替?
にID列順表1から最新の値をIDごとに1つだけの行を持つ表2 ID列への外部キーになりますTable 1
ID FK END_DTTM
1 1 01/01/2000
2 1 01/01/2005
3 1 01/01/2012
4 1 01/01/2100
5 2 01/01/1999
6 2 01/01/2100
7 3 01/01/2100
Table 2
ID END_DTTM
1 01/01/2100
2 01/01/2100
3 01/01/2100
ビジネス上の要件は、表2のすべての更新を追跡して特定時点のデータを取得できるようにすることです。これを達成するために、SQL 2016とTemporalテーブルを使用しています。ここでは、Table 2のすべての更新で履歴テーブルにバージョンが自動的に作成されます。
は、私は現在、ひどく遅いカーソルを使用していますが、約30分で71000行を処理している、挿入、更新プロセスを達成するために、テーブルの周り60millionの行を持っています!次のようにクエリをカーソル:実際にはカーソルそのものよりも遅くTADた、
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
Declare @ID as int;
Declare @FK as int;
Declare @END_DTTM as datetime2;
DECLARE @SelectCursor as CURSOR;
SET @SelectCursor = CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR
SELECT [ID],[FK],[END_DTTM] from TABLE1 order by FK,ID;
OPEN @SelectCursor ;
FETCH NEXT FROM @SelectCursor INTO @ID,@FK,@END_DTTM;
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE TABLE2
set
END_DTTM = @END_DTTM
where ID = @FK
IF @@ROWCOUNT = 0
BEGIN
INSERT Table2
(
ID,END_DTTM
)
VALUES (
@FK,@END_DTTM
)
END
FETCH NEXT FROM @SelectCursor INTO @ID,@FK,@END_DTTM;
END
CLOSE @SelectCursor;
DEALLOCATE @SelectCursor;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
DECLARE @ErrorNumber INT = ERROR_NUMBER();
DECLARE @ErrorLine INT = ERROR_LINE();
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
DECLARE @ErrorState INT = ERROR_STATE();
PRINT 'Actual error number: ' + CAST(@ErrorNumber AS VARCHAR(10));
PRINT 'Actual line number: ' + CAST(@ErrorLine AS VARCHAR(10));
PRINT 'Actual message: ' + CAST(@ErrorMessage AS VARCHAR(4000));
PRINT 'Actual severity: ' + CAST(@ErrorSeverity AS VARCHAR(10));
PRINT 'Actual state: ' + CAST(@ErrorState AS VARCHAR(10));
Insert into ERROR_LOG
(
SOURCE_PRIMARY_KEY
,ERROR_CODE
,ERROR_COLUMN
,ERROR_DESCRIPTION
)
VALUES
(
null,
@ErrorNumber,
@ErrorState,
@ErrorMessage,
'Error!'
);
Throw;
-- RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH
END;
私は、CTEを使用してみましたが、私はそれでどんなパフォーマンスの向上を見ていません。
上記のテーブルベースの操作を使用して、テーブル1と更新2のすべての行を処理し、一時テーブルが更新を取得して変更を追跡できるようにするには、より良い方法がありますか?
あなたがしようとしているロジックが何であるか説明してください。見知らぬ人がカーソルコードを見つけようとしないでください。 –
ゴードン、私はすでに私のポストで論理を説明しようとしました。このコードは、私がやっていることを示すもので、役に立たないと無視できるものです。私が明確でない場合は、そう言いましょう。私は、例やコードなしでそれを言い換えようとすることができます! – user3363391
希望の結果を表示します。 –