内藤 裕二/ 2023年 9月 8日/ 技術

こんにちは!内藤です!
9月に入り、札幌は朝晩の気温がぐっと低くなってきました。
そろそろ冬の足音が聞こえてきますね。

先日、ある時期の前後でマスタデータに加えられた変更を追跡する機会がありまして、その時使用したdata-diffというツールをご紹介します。

TL;DR;

  • 同じ構造のテーブル同士を比較してくれる
  • データベースの種類が異なっていても比較が可能
  • データサイズが大きくても結構高速に処理してくれる
  • 結果をCSVに変換するスクリプト作成した

data-diff

こちらの記事がかなり詳しいです。

2つのデータベース上のテーブルのデータを比較してくれるのですが、それぞれのデータベースの種類は異なっていてもOKです。
ただし、それぞれに接続可能なドライバ類は予めインストールしておく必要があります。

インストール

pipでインストールです。
接続したいDBに合わせて、プラグインが必要です。
プラグインは「data-diff」の後ろにデータベース種類を付けた形になっています。
例えば MySQL を使用する場合は、

pip install data-diff 'data-diff[mysql]'

のようにインストールします。

データ比較

指定したデータベース・テーブル内のレコードについて、プライマリキーとなるカラムと、比較対象にするカラムを指定します。
比較対象にするカラムは複数指定可能です。

data-diff '<比較するDB1の接続URI>' <テーブル1の名前> '<比較するDB2の接続URI>' <テーブル2の名前> -k <プライマリキーのカラム名> -c <比較対象のカラム名> [-c <比較対象のカラム名その2>...]

--jsonオプションをつけると、結果をjson形式で出力することもできます。

data-diff '<比較するDB1の接続URI>' <テーブル1の名前> '<比較するDB2の接続URI>' <テーブル2の名前> --json -k <プライマリキーのカラム名> -c <比較対象のカラム名> [-c <比較対象のカラム名その2>...]

比較結果をCSVに変換する

data-diffはとても便利なツールなのですが、出力結果がちょっと扱いにくいフォーマットです。
そこで、data-diffで出力したJSON形式の結果ファイルを、各カラムごとに「before」「after」としてcsvに変換するコードを書きました。

動作確認はPython3系でやっています。
とくに依存パッケージはありません。

使い方は、

python format-data-diff.py <data-diffの結果ファイル(json)パス> <変換後のcsvファイルパス>

となります。

動作例

カラムが1つの場合

  • 入力ファイル
    ["-", ["001", "78"]]
    ["+", ["001", "0"]]
    ["-", ["002", "85"]]
    ["+", ["002", "77"]]
    ["-", ["003", "76"]]
    ["+", ["003", "0"]]
    ["-", ["004", "64"]]
    ["+", ["004", "0"]]
    ["-", ["005", "62"]]
    ["+", ["006", "54"]]
  • 変換結果
    key,before_0,after_0
    001,78,0
    002,85,77
    003,76,0
    004,64,0
    005,62,-1
    006,-1,54

カラムが複数の場合

  • 入力ファイル
    ["-", ["001", "78", "A"]]
    ["+", ["001", "0", "B"]]
    ["-", ["002", "85", "A"]]
    ["+", ["002", "77", "A"]]
    ["-", ["003", "76", "B"]]
    ["+", ["003", "0", "B"]]
    ["-", ["004", "64", "C"]]
    ["+", ["004", "0", "C"]]
    ["-", ["005", "62", "A"]]
    ["+", ["006", "54", "A"]]
  • 変換結果
    key,before_0,after_0,before_1,after_1
    001,78,0,A,B
    002,85,77,A,A
    003,76,0,B,B
    004,64,0,C,C
    005,62,-1,A,-1
    006,-1,54,-1,A

参照URL