SQL SERVERのストアドプロシージャを使用した履歴データの移行について
本日は、ソフトウェア開発において最も一般的な履歴データの移行方法についてお話します。移行について話す前に、いくつかの基本的な概念を簡単に紹介します。
1. 履歴データの移行とは?
簡単に言うと、作成から時間が経ち、あまり使われなくなった履歴データを別の場所(別のデータか別のテーブル)に保存することです。
2. 履歴データ移行の目的
使用するデータベースの数を減らす、データのボリュームが大きいほど、長いデータベースは、データを操作する(含む:クエリ、ソート、など)、データのテーブルが数千万レベルに達すると、その後、多条件のマルチテーブルクエリ、応答時間が遅くなる可能性があるためです。(開発者によって書かれたロジックが異なるため、すべてのSQLが効率的に実行されるSQLであることを保証することは不可能です)
ですから、タイムリーに過去のデータを移行していくことは、システム全体のパフォーマンスにとって確実なメリットとなります。
3. 履歴データの移行はいつ行う必要がありますか?
最も単純なケースでは、プログラムの動作が遅くなってきたと感じたときが、履歴データの移行を考え始めるタイミングとなります。
原則的には、サーバー台数が少なく、ハードウェア構成もそれほど高くない中小企業の場合、数千万件のデータが揃うのを待って移行を開始するのではなく、500万件以上のデータから1テーブルでゆっくりと移行を開始するのがよいでしょう。
1年程度は業務データを残したいということであれば、1年前の履歴データをすべて履歴データベースに移行すればよいでしょう。毎日発生するデータ量が多すぎる場合は、一般的にテーブルの自動分割保存を検討する必要がありますが、これを行わなければ、過去3~6カ月分のデータだけをライブビジネスデータベースに保存しておけば、日々の業務に影響を与えることはありません。
4. データ移行の基本的な考え方
1)、1回目の移行で同一のテーブル構造を作成する(1回目の移行前に作成したものであれば可)
2)、データを作成した時期でソートし、最も古いデータNデータをチェックアウトし、同時に履歴テーブルに挿入する。
insert into ... select from
3)、挿入されたデータの正確さをテストし、それがN正しいことを確認します。その後、使用中の業務データベースを削除してください。
4) 移行データの途中でエラーが発生した場合に処理を終了するが、使用中のデータベースを削除することはできないので、開発者にデータの確認をしてもらう必要がある。
5)、移行によるパフォーマンスへの影響にもよりますが、Nはあまり多くても一度に5Wから10Wのバー(サーバーのパフォーマンス構成によっては、一度に1Wから5Wのデータを移行する方が影響が少なくておすすめです)です。多くのデータを移行したい場合は、一括して実行することも検討できます。
5. データ移行用ストアドプロシージャのコード例
コードは以下の通りです。(あまり説明する必要はありません。非常にシンプルなコードで、一目で理解できます)
USE [Tyingsoft.GLPS]
GO
/****** Object: StoredProcedure [dbo]. [TY_SP_ApiRequestToHis] Script Date: 2021-09-16 15:35:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:
-- Create date:
-- Last Edit date:
-- Description: <Interface request log GLPS_APIREQUEST data migration>
-- =============================================
ALTER PROCEDURE [dbo]. [TY_SP_ApiRequestToHis]
-- Add the parameters for the stored procedure here
@PreCountN int = 2000 -- Number of entries per execution N
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @tableDataCount int; -- Number of data items before migration
declare @tableDataCountHis int; -- the number of data items in the historical database before migration
declare @tableDataCount2 int; -- Number of data items after migration
declare @tableDataCount2His int; -- the number of data items in the historical database after migration
declare @maxCreateTime datetime; -- take the maximum creation time of the N data items
declare @maxCreateTimeHis datetime; -- the maximum creation time in the historical database
declare @beginTime datetime; -- start time
declare @endTime datetime; --execution completion time
declare @execTimeMS int; --execution time (in milliseconds)
-- intermediate steps debugger time consuming use
declare @tmpBeginTime datetime; --(temporary) start time of execution
declare @tmpEndTime datetime; --(temporary) execution completion time
declare @tmpExecTimeMS int; --(temporary) execution time (in milliseconds)
select @beginTime = getdate();
-- before migration: query the number of data entries first
select @tableDataCount = count(1) from [Tyingsoft.GLPS].dbo.GLPS_APIREQUEST;
select @tableDataCountHis =count(1) from [Tyingsoft.GLPS_His].dbo.GLPS_APIREQUEST;
print '[Interface request record table (GLPS_APIREQUEST) data migration] start time:' + convert(nvarchar(50),@beginTime,20);
print 'Number of data entries scheduled to be migrated this time: ' + cast( @PreCountN as nvarchar(20));
--create a temporary common expression (the earliest N entries created in the table)
with topNRecord (FCREATETIME)
as
(
select top (@PreCountN) FCREATETIME from GLPS_APIREQUEST order by FCREATETIME
)
--get the maximum creation time in N data
select @maxCreateTime =max(FCREATETIME) from topNRecord
print 'The corresponding migration data FCREATETIME is:' + convert(nvarchar(50),@maxCreateTime,21); -- Convert the date to string format: yyyy-MM-dd HH:mm:ss.fff
select @tmpBeginTime = GETDATE(); --Intermediate step to start timing
-- Step 1: Write N count data to the history database
insert into [Tyingsoft.GLPS_His].dbo.GLPS_APIREQUEST
select * from [Tyingsoft.GLPS].dbo.GLPS_APIREQUEST where FCREATETIME <=@maxCreateTime
select @tmpEndTime = GETDATE(); -- intermediate step timed out
print 'Data migration, insert elapsed time (milliseconds):' +cast( datediff(millisecond,@tmpBeginTime,@tmpEndTime) as nvarchar(20));
-- Step 2: Compare data from historical database
select @maxCreateTimeHis=max(FCREATETIME) from [Tyingsoft.GLPS_His].dbo.GLPS_APIREQUEST
if @maxCreateTime = @maxCreateTimeHis
begin
select @tmpBeginTime = GETDATE(); --Intermediate step starts timing
-- Step 3: After execution, delete the data
delete from GLPS_APIREQUEST where FCREATETIME <=@maxCreateTime
print 'Number of data entries deleted after migration:' + cast( @@ROWCOUNT as nvarchar(50));
select @tmpEndTime = GETDATE(); -- intermediate step timed out
print 'Data migration, deletion elapsed time (milliseconds):' + cast( datediff(millisecond,@tmpBeginTime,@tmpEndTime) as nvarchar(20));
end
else
print 'After migration, date checksum error, data not deleted!!!'
-- After migration: query data count again
select @tableDataCount2 = count(1) from [Tyingsoft.GLPS].dbo.GLPS_APIREQUEST;
select @tableDataCount2His =count(1) from [Tyingsoft.GLPS_His].dbo.GLPS_APIREQUEST;
print 'Number of data items in GLPS_APIREQUEST before migration:' + cast(@tableDataCount as nvarchar(20))
+ ',Number of data entries after migration:' + cast(@tableDataCount2 as nvarchar(20))
+ ',Difference: ' + cast((@tableDataCount2-@tableDataCount) as nvarchar(20));
print 'Number of data entries in His.GLPS_APIREQUEST before migration:'
+ cast(@tableDataCountHis as nvarchar(20))
+ ',Number of data entries after migration:' + cast(@tableDataCount2His as nvarchar(20))
+ ',Difference: '+cast((@tableDataCount2His-@tableDataCountHis) as nvarchar(20));
print 'Note: The formal environment has always had data changes, so there will be some deviation!' ;
select @endTime = GETDATE();
print 'Total elapsed time (milliseconds):' +cast( datediff(millisecond,@beginTime,@endTime) as nvarchar(20));
END
では、テスト用のデータベースで試してみましょう。
6. 使用シナリオに関する特記事項
この方法は、insert into ... select from を使ってデータを移行する方法です。この考え方は、最もシンプルなデータ移行ロジックですが、データ量が少ない場合(一般的に500万件未満のテーブルデータ)、データ量が500万件を超える場合は、この方法を使用しないでください。
また、この方法はデータベースにSQLで直接アクセスするため、現在のビジネスライブラリと過去のデータの両方にアクセスできること(つまり同じデータベースインスタンス)が必要で、オフサイトの場合は別のデータベースを扱う方法がない、という事実もあります。
そのため、この方法は単純な履歴データの移行シナリオにのみ適しており、使用前提条件が限定されているため、小規模なプロジェクトに向いています。
大容量のデータ(1つのテーブルで1000万以上)や、現在の業績指標に影響を与えないデータ移行方法については、次の記事で詳しく解説しています。
SQL SERVERのストアドプロシージャのデータ移行については、スクリプトハウスの過去記事を検索していただくか、引き続き以下の関連記事をご覧ください。
関連
-
SQLにおける3つの重複排除手法の概要
-
あるユーザーの連続ログイン日数を求めるSQLクエリ
-
DataGrip Formatting SQLの実装(カスタムSqlフォーマット)
-
SQLServerクリーンアップログファイルのメソッド事例詳細
-
SQLの書き方--行ごとの比較
-
Filestreamの簡単な使い方まとめ
-
SQL Server のフィルタードインデックスによるクエリ文の改善に関するパフォーマンス分析
-
SqlServerデータベースリモート接続ケースチュートリアル
-
SQLServerにおけるJSONドキュメント型データのクエリ問題を解決する。
-
sql serverで最初の1000行のデータを削除する方法の例
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン