データマネジメントチームの森 達也です。
本記事では、データ検証の方法について、具体的なSQLやWorkflowを用いてご紹介します。
データ検証とは
データ検証とは、実装したデータや処理が正しいか確認することです。Treasure Data CDPではSQLやWorkflowなどで様々な処理を実装可能ですが、ロジックが複雑になればなるほど、不具合が生じる可能性も高まります。そのためデータ検証をすることによって、データの正しさや要件に沿っているかなどを確かめる必要があります。これはソフトウェア開発の最終プロセスとして必ずテストをして、成果物の品質を担保しているのと同じで事です。本記事では、実践的な検証方法をソースコードとともにご紹介いたします。
データ検証のポイント
実際の検証方法をご説明する前に、データ検証のポイントを考えてみたいと思います。データの性質や処理内容、個人の実装のクセもよりますが、共通して重要なのは次の3点であると考えています。
要件と仕様の理解
正しく検証をするためには、データ要件や仕様を正しく理解する必要があります。データ検証は仕様が実装されているか、一つ一つ確認していくプロセスなので、要件や仕様をしっかりと理解している事が大前提になります。
カバレッジを意識する
カバレッジとは処理の網羅率になり、より抜け漏れなく検証する(=カバレッジを高める)事で、バグの抑える事ができるといえます。データ検証でもカバレッジが十分であるか、意識する必要があります。もし今あるデータだけでは全ての処理を検証できない場合は、テストデータを用意するなどした方が良いでしょう。ただしカバレッジを意識しながらも、作業時間は有限なので、ミスの許されない重要なデータや、バグが生じやすい複雑な処理を重点的に検証する事も重要です。
テストを自動化する
初期構築が完了したとしても、データ基盤に処理追加やデータソースの仕様変化は付き物です。データや処理の変化に対応するために、検証は自動化しておく事が望ましいでしょう。例えば処理を変更する度に、手動でテストをするのは非効率的ですし、データの変化に気づけない事もあります。データ処理の中で検証を自動化しておくと、ソースデータの異常検知や、デグレの防止、工数削減に役立ちます。なおこのアプローチは、ソフトウェア開発の分野では、テスト駆動開発と呼ばれています。
検証ケースの分類
ここではスキーマの検証と、他データとの比較検証の各テストケースを、サンプルSQLと共にご紹介いたします。
スキーマの検証
Plazma DBではRDBの諸制約を設定できないため、カラムの値が定義通りであるか、想定外のデータが入っていないかを、テーブル単体で確認します。4つの代表的な制約の検証方法をご紹介いたします。
UNIQUE:一意であること
カラムの値に重複がないか、レコード数とPKのユニーク数が一致するかを確認します。
SELECT COUNT(1) = COUNT(DISTINCT pk) AS check FROM tbl
NOT NULL:NULLでないこと
NULLのレコード数が0であることを確認します。
SELECT COUNT(1) = 0 AS check FROM tbl WHERE col IS NULL
CHECK:定義されたフォーマットであること
指定フォーマット以外のレコード数が0であることを確認します。(例:値が「PC」「SP」のいずれか)
SELECT COUNT(1) = 0 AS check FROM tbl WHERE NOT REGEXP_LIKE(col, '(PC)|(SP)')
FOREIGN KEY:キーが他テーブルに存在すること
外部キーでJOINできなかったレコード数が0であることを確認します。
SELECT COUNT(1) = 0 AS check FROM tbl1 LEFT JOIN tbl2 ON tbl1.key = tbl2.key WHERE tbl2.key IS NULL
他データとの比較検証
次に他データや基準値との比較によって、データに問題ないことを確認する場合です。スキーマレベルでは検証できないカスタムケースとして設定します。比較の例としては、次のものが挙げられます。
- 正解データとレコードを突き合わせて一致すること
- 集計値の比較(レコード数、平均/最大/最小値など)
例. レコード数が元テーブルと一致すること
例. 前週から数値が増加すること
それぞれの検証方法をご紹介いたします。
レコードの突き合わせ
正解データと相互にEXCEPT演算して差分をとり、完全一致しているかを確認します。実行結果のレコード数が0なら両テーブルは同一と言えます。
SELECT COUNT(1) = 0 AS check FROM ( SELECT * FROM target_tbl EXCEPT SELECT * FROM answer_tbl UNION ALL SELECT * FROM answer_tbl EXCEPT SELECT * FROM target_tbl )
集計値の比較(レコード数の例)
レコード数が元テーブルと一致するかを確認します。
SELECT (SELECT COUNT(1) FROM result_tbl) = (SELECT COUNT(1) FROM source_tbl) AS check
集計値の比較(平均値の例)
平均値が先週時点から増加したかを確認します。
SELECT (SELECT AVG(col) FROM tbl_latest) > (SELECT AVG(col) FROM tbl_last_week) AS check
データ検証とは
テスト自動化の方法として、Workflowのデータ処理に検証を組み込む方法をご紹介します。検証をWorkflow化する事で、ソースデータの異常検知、デグレの防止、テスト工数の削減に寄与することが出来ます。ここではデータ加工後に検証タスクを実行して、NGの場合はアラート通知を行うWorkflowを作成します。
# データ処理のSQL +create_latest_table: td>: query: | WITH latest AS ( SELECT pk, MAX(time) AS time FROM tbl GROUP BY 1 ) SELECT tbl.* FROM tbl INNER JOIN latest ON tbl.pk = latest.pk create_table: latest_tbl # データ検証のSQL(例としてUNIQUE制約) # store_last_resultsで検証結果を保持する +validate: td>: query: | SELECT COUNT(1) = COUNT(DISTINCT pk) AS check FROM latest_tbl store_last_results: true # 検証結果に応じた処理を記載する # NGの場合はWorkflowをFailさせる +fail_if_not_unique: if>: ${td.last_results.check} _else_do: +fail: fail>: 'Table has duplicate records for PK'
おわりに
本記事ではデータ検証の考え方と、Treasure Data CDPにおける検証方法をご紹介しました。データを最大限に活用するためには、データ品質を高めることが重要で、そのためにはデータ検証への取り組みが不可欠です。本記事がその一助になれれば幸いです。
最後までお読みいただき、ありがとうございました。