はじめに
こんにちは、ニジボックスでBIエンジニアをしている中根です。
普段の業務ではリクルートのプロダクトであるAirペイやAirペイQR、RMB(株式会社リクルートMUFGビジネス)のプロダクトであるCOIN+といった決済に関わるプロダクトのデータマート作成等に携わっています。
データマートはKPIや重要指標のモニタリングに使用されるため、データ品質の担保が非常に重要です。
今回はテストのフローに基礎統計量の調査を組み込んだことと実装済みのロジックであってもそれが正しいか疑うことによって既存のデータマートに潜んでいたバグを発見した事例についてお話しします。
バグの概要
結論から書くと外部結合に使用するキーを間違えていたことで本来取得できているはずのレコードの内容が取得できていない状態になっていました。
まずはバグの原因になっていたテーブルについて簡単に整理します。
| テーブル | 役割 | PK | FK(結合用) |
|---|---|---|---|
| A | トランザクションテーブル | トランザクションID(A独自のID) | - |
| B | Aのエラー履歴を持つトランザクションテーブル | トランザクションID(B独自のID) | AのトランザクションID |
いずれもPKとしてトランザクションIDを持ちますがそれらは対応しているわけではなく、Bは別のカラムでAのトランザクションIDをFKとして持っています。

本来想定されていた処理はテーブルAに対してテーブルBをleft joinしてエラーの内容を取得することでした。
この結合に必要なキー指定はA.トランザクションID = B.AのトランザクションIDが正ですが、誤ってA.トランザクションID = B.トランザクションIDとなっていました。
トランザクションIDの採番ロジックが異なっていたため誤って紐付くレコードが存在していなかったことは不幸中の幸いで、全てのトランザクションが正常処理扱いになっていました。
このデータマートはアクティブユーザーの集計に使用されており、このバグによって「トランザクションがエラーのみのユーザー(例:初めての操作でエラーが出たので使うのをやめてしまったユーザー)」もアクティブユーザーとしてカウントしてしまっていました。
バグを発見した経緯
当時、チーム内で作成したばかりのデータ品質チェックツールを試運転しており、作業中のデータマートにも導入していました。このツールには、クエリ結果の基礎統計量を可視化するステップが組み込まれていました。
基礎統計量の可視化ステップではクエリ結果の様々な統計結果を確認することができます。今回バグの発見のきっかけになった項目は非nullレコード数で、当該カラムはこれが0でした。つまりテーブルBから引っ張ってきているはずの「エラー内容カラム」が全てnullでした。
この時、この非nullレコード数0をどう解釈するか2択でした。
- 外部結合でエラーの内容を取得するロジックのため全てのレコードがnullであることは起こり得るため問題無い
- 外部結合で結合ミスが起こっていた場合は全てのレコードがnullになるので結合ミスが発生している可能性がある
当該カラムのロジックは今回追加した部分ではなかったため過去にテストを実施しているはずで判断に迷いましたが、700万件のトランザクションでエラーが0件はあり得ないという直感で結合ミスを疑い調査を進めた結果、ロジックミスの発見に至りました。
振り返り
一般的にエンハンス作業でのテストケースは「変わるべき部分が想定通りに変わっているか」と「変わらないべき部分が変わっていないか」を確認するために設計されます。今回のように1度埋め込まれてしまったバグを後からテストによって見つけ出すには網羅的なテストケースの設計が必要であり、作業工数との兼ね合いから重要度によるテストケースの絞り込みを行うと実装済みのカラムに対する綿密なテストはどうしても優先度が低くなってしまいます。
今回の件でデータの状態をチェックする基礎統計量調査がテストケースに対する補完としてある程度機能することが実績として得られました。
ただ難しい点として、基礎統計量の調査のみではOK/NGで結果が出るテストではないため、結果に対する異常の検知はテスト実施者のドメイン知識や直感に委ねられてしまうという課題があります。今回私が異常だと判断した理由は「結合ミスが発生していた場合この状態になる可能性がある」ことを知っていたからで、特定の状態が特定のミスによって引き起こされるということを一般化してテストケースに落とし込んでいくことが今後の課題になります。
外部結合の危険性
内部結合はミスがあればレコード数が0になったり増殖したりといった影響が明確に出ますが、外部結合の場合はもう少し踏み込んで確認を行わなければ異常に気付けないことがあります。
実装タイミングであれば非nullレコード数が想定通りであるかどうかのテストは非常に有効ですが、想定の数値はテストの度に算出する必要があり実装後だとテストケースとしては優先度が低くなります。
一方、非null率が100%かどうかであれば全てのカラムに対して実施することも容易で、外部結合に限らないカラムの異常に気付く機会を作ることができます。
おわりに
私たちデータベースを扱うエンジニアはデータの品質に常に疑いの目を向ける必要がありますが、実際に異常を見つけるにはその機会が必要になります。
基礎統計量の調査によってデータ全体を網羅的に見てみることと既存のロジックであっても疑いの目を持つことによって不具合の発見、さらにはテストの品質向上に繋がります。
基礎統計量の調査は新規のカラムだけでなく既存のカラムに対してもロジックミスが発生していないか疑いの目を向けることができる良い機会となります。データベースを扱う方はぜひとも基礎統計量の調査をテストに取り入れてみてはいかがでしょうか?
この記事の中で出てきたテストツールの作成者である村上さんのアドベントカレンダーが1週間後の23日に公開予定です。テストツールについて詳細が気になる方はぜひ併せてご覧ください。
公開されたので追記しました。