データ移行は別トラックだ
一言でいうと
データ移行は、開発が終わってから始める作業ではなく、開発と並行して進める別トラックであり、移行で見つかるデータの問題が設計を変えることもあります。
なぜこれが問題なのか
移行を後半の作業に先送りすると、発見の時期が遅れます。しかも移行で出てくる問題は、たいてい選択肢が時間に左右される問題です。
新しいスキーマでNOT NULLにしたカラムが、レガシーでは30%空だとします。6か月前に知っていれば、スキーマを直すか、デフォルト値のルールを合意するか、業務側に整理を依頼できます。サービスイン2週間前に知ると、残る選択肢は1つだけです。とにかく埋めることです。そして、そうして埋めた値は、何年もそのシステムのデータとして残ります。
移行はプロジェクト後半の作業ではありません
次世代プロジェクトの振り返りで、繰り返し出てくる教訓があります。
データ移行は、プロジェクトの初期から別トラックで管理する必要があります。
理由は単純です。移行は開発が終わらないと始められない作業ではなく、開発と並行して進めるべき作業だからです。そして、移行の過程で見つかるデータの問題が、設計を変えることもあります。
実際によく起こること:
- 新しいスキーマで
NOT NULLにしたカラムが、レガシーでは30%空です - 新しいコード体系にマッピングされないレガシーのコード値が、47個出てきます
- レガシーに、同じ顧客が名前の表記だけ違う形で3件ずつあります
これをサービスイン2週間前に発見すると、選択肢がありません。6か月前に知っていれば、スキーマを直すか、クレンジングルールを合意するか、業務の整理を依頼できます。
移行リハーサルは3回
大規模プロジェクトの移行計画には、リハーサルが何回も入ります。
1차 리허설 (D-90) : 절차 확인. 시간이 얼마나 걸리는가
2차 리허설 (D-30) : 데이터 품질 확인. 정제 규칙 검증
3차 리허설 (D-7) : 실전과 동일 조건. 시간·순서·인원 확정
このコードブロックの韓国語は、1回目(D-90)は手順の確認で時間がどれだけかかるか、2回目(D-30)はデータ品質の確認とクレンジングルールの検証、3回目(D-7)は本番と同じ条件で時間・順序・人員を確定する、という意味です。
リハーサルの本当の成果物はデータではなく所要時間の実測値です。「移行に4時間かかります」を、見積もりではなく測定で言えて初めて、カットオーバー計画のタイムラインが成り立ちます。そして、たいてい最初のリハーサルで、予想より2–3倍かかることがわかります。
AS-IS → TO-BEマッピング定義書
移行の核心的な成果物です。カラム単位で次のように書きます。
| TO-BEテーブル | カラム | AS-ISソース | 変換ルール | 未マッピング時 |
|---|---|---|---|---|
| CUSTOMER | CUST_NM | TB_CUST.NAME | TRIM、空白の正規化 |
エラー |
| CUSTOMER | REG_DT | TB_CUST.REGDATE | YY/MM/DD → YYYYMMDD |
19000101 |
| CUSTOMER | GRADE_CD | TB_CUST.LEVEL | コードマッピング表を参照 | 99(その他) |
| ORDERS | ORD_STS_CD | TB_ORD.STATUS | コードマッピング表を参照 | 移行除外 |
「未マッピング時」の列が核心です。マッピングされない値が出てきたときに、エラーとして扱うのか、デフォルト値を入れるのか、その行を除外するのか。これを決めないと、開発者が勝手に処理し、その結果は「件数が合わない」という形で返ってきます。
そして除外した件は必ず一覧として残します。「1,200件中1,187件を移行、13件を除外」までが結果であり、その13件が何なのかを答えられなければなりません。
クレンジング(cleansing)で実際にすること
レガシーデータは、たいていこうです。
| 症状 | 例 | 処理 |
|---|---|---|
| 前後の空白 | " 홍길동 "(韓国語の人名) |
TRIM |
| 日付形式の混在 | 20260801、2026-08-01、26/08/01 |
1つに正規化します |
| 文字列のNULL | 値が文字列の"NULL"または"null" |
本物のNULLにします |
| 金額の書式 | "1,250,000" |
カンマを除去して、数値にします |
| 重複 | 同じキーが複数件 | ルールを決めて1件だけ残します(通常は最新の更新日) |
| コード値の不一致 | 廃止されたコード、誤記 | マッピング表、またはその他コード |
| 文字化け | ????? |
ソースから再抽出します |
重複排除のルールは、必ず業務側と合意する必要があります。「最新のものを残す」が自然に見えますが、最新の行のほうがかえって不完全な場合もあります。技術的な判断ではなく、業務上の判断です。
検証は4つの層で
移行後の検証は、下から上に積み上げます。1つでも抜けると穴が生まれます。
1. 스키마 검증 테이블·컬럼·타입·제약·인덱스가 의도대로 있는가
2. 데이터 검증 건수 · 합계 · NULL 개수 · 체크섬
3. 성능 검증 주요 쿼리의 실행계획과 응답시간
4. 애플리케이션 핵심 업무 시나리오 스모크 테스트
このコードブロックの韓国語は、検証の4つの層を示しています。スキーマ検証(テーブル・カラム・型・制約・インデックスが意図どおりにあるか)、データ検証(件数・合計・NULLの個数・チェックサム)、性能検証(主要クエリの実行計画と応答時間)、アプリケーション(主要な業務シナリオのスモークテスト)です。
項目2でチェックサムを使う理由をあらためて強調します。件数と合計だけでは、「1件が抜けて別の1件が2倍になった」状況を検出できません。ソートしたキー一覧のハッシュを比較すれば、そのような場合まで検出できます。
-- 개념적으로: 키를 정렬해 이어 붙인 문자열의 해시
SELECT md5(group_concat(CUST_ID, ',' ORDER BY CUST_ID)) FROM CUSTOMER;
検証のコストと信頼度は、次のように違います。
| 方法 | コスト | 信頼度 |
|---|---|---|
| サンプル確認 | 低 | 低–中 |
| 集計(件数・合計) | 低 | 中の上 |
| チェックサム | 中 | 高 |
| 全件比較 | 高 | 非常に高(金融など整合性が必須の領域) |
移行結果確認書
口頭での確認で終わらせてはいけません。文書として残します。
## 이관 대상
CUSTOMER 원천 1,200건 → 이관 1,187건, 제외 13건
ORDERS 원천 45,320건 → 이관 45,320건, 제외 0건
## 제외 사유
코드 미매핑 9건 (목록: excluded_code.csv)
필수값 누락 4건 (목록: excluded_null.csv)
## 검증 결과
건수 일치 OK
금액 합계 일치 OK (원천 8,213,400,000 / 대상 8,213,400,000)
키 체크섬 일치 OK
## 재이관 대상
13건 - 업무 정리 후 D+3 재이관 예정, 담당 ○○○
## 확인
수행사 ___ 발주사 ___
このコードブロックの韓国語は、移行対象(CUSTOMERはソース1,200件から移行1,187件・除外13件、ORDERSはソース45,320件から移行45,320件・除外0件)、除外理由(コード未マッピング9件、必須値の欠落4件)、検証結果(件数一致、金額合計一致、キーのチェックサム一致がいずれもOK)、再移行対象(13件。業務整理後にD+3で再移行する予定)、確認(受託ベンダーと発注元の署名欄)を記した確認書の例です。
この文書があれば、サービスイン後の「データがないのですが」という問い合わせに、「その13件は移行除外の対象で、D+3に再移行の予定です」と答えられます。なければ、最初から調べ直さなければなりません。
移行に失敗したときの原則
最後に1つ。移行中に問題が起きたときの原則です。
データに手を加える復旧は、最後の手段です。
順序は次のとおりです。
- フィーチャーフラグで新しい経路をオフにします(可能であれば)
- トラフィックを以前のシステムに戻します
- それでもだめなら、スキーマをロールバックします
- 最後に、データを復旧します(バックアップからの復元、ポイントインタイムリカバリ)
4つ目が最も時間がかかり、最も危険です。だから、前の3つの段階を事前に準備しておくことが、カットオーバー計画の実力です。
現場での姿
移行が終わったかどうかを判断する基準も、よくずれます。「エラーなしで動いた」は、終わったという意味ではありません。突合をしてみると、件数が違う、金額の合計が合わないということがよくありますが、その差が説明できる差かどうかが本当の基準です。
重複排除で20件減ったなら、件数が合わないのは当然で、それは正常です。逆に、何の理由もなく3件が欠けていれば、それは事故です。そのため、突合表には、差を0にするための欄ではなく、差とその理由を書く欄がなければなりません。
除外された件の一覧も、必ず残します。このファイルがなければ、サービスイン後の「うちの顧客が移行されていない」という問い合わせに答える方法がなく、そのときに数え直すことは不可能です。