DMF による品質チェック時に違反の条件を定義できる Expectation を試してみた #SnowflakeDB
はじめに
2025年8月のアップデートで、Data metric function(DMF)をテーブルなどのオブジェクトに割り当てる際に expectations(期待値)として、違反となる条件を設定できる機能が一般提供となりました。
こちらの機能を試してみた内容を、本記事でまとめます。
アップデートの概要
DMF をテーブルカラムなどオブジェクトに追加することで、データの状態や整合性確認を行えます。Snowflake 側で定義済みのシステム DMF には、NULL 値やブランクのカウント、鮮度テストに使える FRESHNESS などが用意されています。
DMF は単体として使用したり、テーブルに DATA_METRIC_SCHEDULE を設定することで DMF をテーブルカラムに関連付け、定期実行することも可能です。
定期実行された結果は専用のイベントテーブルやビューから確認できます。
これまで、DMF によるデータ品質チェックは、例えば NULL 値のカウント数などの結果をVALUE
列に返す形式でした。
+-------------------------------+------------+-------------+----------------+----------------+-------+
| SCHEDULED_TIME | TABLE_NAME | METRIC_NAME | ARGUMENT_TYPES | ARGUMENT_NAMES | VALUE |
|-------------------------------+------------+-------------+----------------+----------------+-------|
| 2025-09-03 09:20:00.000 +0900 | EMPLOYEES | NULL_COUNT | [ | [ | 3 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
+-------------------------------+------------+-------------+----------------+----------------+-------+
今回のアップデートにより、DMF をテーブルに追加する際、データ品質の合格基準を「期待値(Expectation)」として定義できるようになりました。これにより、DMF の実行結果がこの期待値に合致するかどうかをブール値(TRUE
/FALSE
)で判定できます。
期待値違反の判定式や結果は、専用のビューから直接確認可能です。この機能によって、データ品質チェックの閾値判定ロジックをアラートやストアドプロシージャなどで別途実装する必要がなくなり、通知などの後続処理をよりシンプルに構築できるようになります。
試してみる
本機能については以下に記載があります。
検証用のテーブルを作成
以下の手順で検証に使用するテーブルを作成しました。
-- サンプルテーブルを作成
CREATE OR REPLACE TABLE sample_data_table (
id INT,
product_name VARCHAR,
inventory_count INT,
last_updated TIMESTAMP_LTZ
);
-- データ品質が "良い" 状態のデータを挿入 (期待値に合致するデータ)
INSERT INTO sample_data_table (id, product_name, inventory_count, last_updated) VALUES
(1, 'Laptop', 150, CURRENT_TIMESTAMP()),
(2, 'Mouse', 50, CURRENT_TIMESTAMP()),
(3, 'Keyboard', 25, CURRENT_TIMESTAMP()),
(NULL, 'Monitor', 5, '2023-01-01T00:00:00Z'),
(5, 'Webcam', 0, CURRENT_TIMESTAMP());
DMF は以下のように実行できます。
--null count
>SELECT snowflake.core.null_count (SELECT id FROM sample_data_table);
+--------------------------------------------------------------+
| SNOWFLAKE.CORE.NULL_COUNT (SELECT ID FROM SAMPLE_DATA_TABLE) |
|--------------------------------------------------------------|
| 1 |
+--------------------------------------------------------------+
--freshness:タイムスタンプ列の最大値と、データメトリック関数が実行される予定時刻との差を秒単位で返す
--8:31:45 に実行
>SELECT snowflake.core.FRESHNESS (SELECT last_updated FROM sample_data_table);
+-----------------------------------------------------------------------+
| SNOWFLAKE.CORE.FRESHNESS (SELECT LAST_UPDATED FROM SAMPLE_DATA_TABLE) |
|-----------------------------------------------------------------------|
| 29 |
+-----------------------------------------------------------------------+
--タイムスタンプ列の最大値
>SELECT MAX(last_updated) FROM sample_data_table;
+-------------------------------+
| MAX(LAST_UPDATED) |
|-------------------------------|
| 2025-09-02 20:31:16.413 +0900 |
+-------------------------------+
テーブルに DMF と期待値を追加
前提として、テーブルに DMF を関連付けるには、テーブルに DMF のスケジュールを設定する必要があります。
ここでは5分ごとに実行するように設定しました。
ALTER TABLE sample_data_table SET DATA_METRIC_SCHEDULE = '5 MINUTE';
DMF を追加します。この際、あわせてEXPECTATION
で期待値を設定できます。ここでは、指定のカラム(id)のNULL値のカウント数が1未満であることを条件として設定しています。
ALTER TABLE sample_data_table
ADD DATA METRIC FUNCTION SNOWFLAKE.CORE.NULL_COUNT ON (id)
EXPECTATION null_id_exp (VALUE < 1);
期待値を設定する際のポイントは以下です。
- 期待値には、それが満たされたかどうかを判断するブール式含まれる
VALUE
は、DMFによって返された値を表すnull_id_exp
は期待値を識別するために使用される任意の文字列です- 複数の期待値を追加することも可能(後述)
DMF が追加されると、ここではスケジュールに沿って実行されます。
DMF の結果を確認
期待値を含む DMF の結果は以下のテーブルやビューで確認できます。
- SNOWFLAKE.LOCAL.DATA_QUALITY_MONITORING_RESULTS_RAW
- 品質結果の生データが格納される専用のイベント テーブル
- DATA_QUALITY_MONITORING_EXPECTATION_STATUS ビュー
- フラット化された結果を確認できる SNOWFLAKE.LOCAL スキーマ内のビュー
- DATA_QUALITY_MONITORING_EXPECTATION_STATUS 関数
- 指定のオブジェクトについて、期待値を伴う DMF の実行結果を返す
基本的にはフラット化された DATA_QUALITY_MONITORING_EXPECTATION_STATUS を使うことになると思います。以下のような内容となっており、[EXPECTATION_VIOLATED] カラムに DMF の実行結果が期待値に違反するかどうかの結果が格納されます。
ここでは、[id] カラムに NULL があるので、違反として記録されています。(違反する場合はTRUE
となります。)
>SELECT * FROM SNOWFLAKE.LOCAL.DATA_QUALITY_MONITORING_EXPECTATION_STATUS;
+-------------------------------+--------------------+-------------------------------+----------+-------------------+--------------+----------------+-----------+-------------+---------------+-----------------+--------------------+--------------+----------------+----------------+--------------------------------------+-------+------------------+--------------------------------------+------------------------+----------------------+
| SCHEDULED_TIME | CHANGE_COMMIT_TIME | MEASUREMENT_TIME | TABLE_ID | TABLE_NAME | TABLE_SCHEMA | TABLE_DATABASE | METRIC_ID | METRIC_NAME | METRIC_SCHEMA | METRIC_DATABASE | METRIC_RETURN_TYPE | ARGUMENT_IDS | ARGUMENT_TYPES | ARGUMENT_NAMES | REFERENCE_ID | VALUE | EXPECTATION_NAME | EXPECTATION_ID | EXPECTATION_EXPRESSION | EXPECTATION_VIOLATED |
|-------------------------------+--------------------+-------------------------------+----------+-------------------+--------------+----------------+-----------+-------------+---------------+-----------------+--------------------+--------------+----------------+----------------+--------------------------------------+-------+------------------+--------------------------------------+------------------------+----------------------|
| 2025-09-02 20:40:00.000 +0900 | NULL | 2025-09-02 20:40:26.814 +0900 | 7182 | SAMPLE_DATA_TABLE | PUBLIC | TEST_DB | NULL | NULL_COUNT | CORE | SNOWFLAKE | DOUBLE | [ | [ | [ | 3555365e-d67c-446f-ac09-ec21881d38ee | 1 | NULL_ID_EXP | 7f154f50-5f26-4ab2-b114-295abf093e4a | VALUE < 1 | True |
| | | | | | | | | | | | | 15383 | "COLUMN" | "ID" | | | | | | |
| | | | | | | | | | | | | ] | ] | ] | | | | | | |
+-------------------------------+--------------------+-------------------------------+----------+-------------------+--------------+----------------+-----------+-------------+---------------+-----------------+--------------------+--------------+----------------+----------------+--------------------------------------+-------+------------------+--------------------------------------+------------------------+----------------------+
データを修正後、実行される結果を確認します。修正後に実行された DMF の結果では、[EXPECTATION_VIOLATED] がFALSE
となっています。
--データを修正
UPDATE sample_data_table
SET id = 4
WHERE product_name = 'Monitor' AND id IS NULL;
--最新の結果はfalseになる
>SELECT
SCHEDULED_TIME
,TABLE_NAME
,METRIC_NAME
,ARGUMENT_NAMES
,EXPECTATION_NAME
,EXPECTATION_EXPRESSION
,EXPECTATION_VIOLATED --TRUEの場合、期待値に違反
FROM SNOWFLAKE.LOCAL.DATA_QUALITY_MONITORING_EXPECTATION_STATUS
ORDER BY SCHEDULED_TIME DESC;
+-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------+
| SCHEDULED_TIME | TABLE_NAME | METRIC_NAME | ARGUMENT_NAMES | EXPECTATION_NAME | EXPECTATION_EXPRESSION | EXPECTATION_VIOLATED |
|-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------|
| 2025-09-02 20:50:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | NULL_ID_EXP | VALUE < 1 | False |
| | | | "ID" | | | |
| | | | ] | | | |
| 2025-09-02 20:45:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | NULL_ID_EXP | VALUE < 1 | True |
| | | | "ID" | | | |
| | | | ] | | | |
| 2025-09-02 20:40:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | NULL_ID_EXP | VALUE < 1 | True |
| | | | "ID" | | | |
| | | | ] | | | |
+-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------+
他の DMF と期待値を追加
別の DMF と期待値を設定してみます。タイムスタンプ列があるので、鮮度に関するチェックを実施します。
-- FRESHNESSと期待値を追加:タイムスタンプ列の最大値が、DMF実行タイミングの5分以内か判定
ALTER TABLE sample_data_table
ADD DATA METRIC FUNCTION SNOWFLAKE.CORE.FRESHNESS ON (last_updated)
EXPECTATION freshness_exp (VALUE < 1500);
結果を確認します。初回は条件に収まるため違反となっていませんが、2回目に実行された際は、違反となっています。
※サンプルテーブルは何度か作り直しているので、先の例と[last_updated]カラムの値が異なります
>SELECT
SCHEDULED_TIME
,TABLE_NAME
,METRIC_NAME
,ARGUMENT_NAMES
,EXPECTATION_EXPRESSION
,EXPECTATION_NAME
,EXPECTATION_VIOLATED --TRUEの場合、期待値に違反
FROM SNOWFLAKE.LOCAL.DATA_QUALITY_MONITORING_EXPECTATION_STATUS
WHERE METRIC_NAME = 'FRESHNESS'
ORDER BY SCHEDULED_TIME DESC;
+-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------+
| SCHEDULED_TIME | TABLE_NAME | METRIC_NAME | ARGUMENT_NAMES | EXPECTATION_NAME | EXPECTATION_EXPRESSION | EXPECTATION_VIOLATED |
|-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------|
| 2025-09-02 21:00:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | FRESHNESS_EXP | VALUE < 1500 | True |
| | | | "LAST_UPDATED" | | | |
| | | | ] | | | |
| 2025-09-02 20:55:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | FRESHNESS_EXP | VALUE < 1500 | False |
| | | | "LAST_UPDATED" | | | |
| | | | ] | | | |
+-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------+
複数の期待値を設定
ある DMF に複数の期待値を設定することも可能です。鮮度に関するテストでこちらを試してみます。
この場合は、以下のようにそれぞれの期待値名(lessThan25Mins
, lessThan45Mins
)を指定します。
--カラムからDMFを削除
ALTER TABLE sample_data_table
DROP DATA METRIC FUNCTION SNOWFLAKE.CORE.FRESHNESS
ON (last_updated);
--条件を変更し追加
ALTER TABLE sample_data_table
ADD DATA METRIC FUNCTION SNOWFLAKE.CORE.FRESHNESS ON (last_updated)
EXPECTATION lessThan25Mins (VALUE < 1500), lessThan45Mins (VALUE < 2700);
DMF の実行結果を確認します。出力は以下のようになり、期待値名([EXPECTATION_NAME])毎に確認できます。
--結果を確認 ※関連するレコードのみ抜粋
--期待毎に見える
>SELECT
SCHEDULED_TIME
,TABLE_NAME
,METRIC_NAME
,ARGUMENT_NAMES
,EXPECTATION_NAME
,EXPECTATION_EXPRESSION
,EXPECTATION_VIOLATED --TRUEの場合、期待値に違反
FROM SNOWFLAKE.LOCAL.DATA_QUALITY_MONITORING_EXPECTATION_STATUS
WHERE METRIC_NAME = 'FRESHNESS' ORDER BY SCHEDULED_TIME DESC;
+-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------+
| SCHEDULED_TIME | TABLE_NAME | METRIC_NAME | ARGUMENT_NAMES | EXPECTATION_NAME | EXPECTATION_EXPRESSION | EXPECTATION_VIOLATED |
|-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------|
| 2025-09-02 21:15:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | LESSTHAN45MINS | VALUE < 2700 | False |
| | | | "LAST_UPDATED" | | | |
| | | | ] | | | |
| 2025-09-02 21:15:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | LESSTHAN25MINS | VALUE < 1500 | True |
| | | | "LAST_UPDATED" | | | |
| | | | ] | | | |
+-------------------------------+-------------------+-------------+------------------+------------------+------------------------+----------------------+
DMF の結果を確認
期待値を含む DMF であっても、これまでのように DMF の実行結果は DATA_QUALITY_MONITORING_RESULTS ビューに記録されます。この場合は、[VALUE] 列に実行結果が格納されています。
通知を構成する際は、条件を満たすかどうかを別途判断するロジックを追加する必要があります。
>SELECT
SCHEDULED_TIME
,TABLE_NAME
,METRIC_NAME
,ARGUMENT_TYPES
,ARGUMENT_NAMES
,VALUE
FROM SNOWFLAKE.LOCAL.DATA_QUALITY_MONITORING_RESULTS
ORDER BY SCHEDULED_TIME DESC;
+-------------------------------+-------------------+-------------+----------------+------------------+-------+
| SCHEDULED_TIME | TABLE_NAME | METRIC_NAME | ARGUMENT_TYPES | ARGUMENT_NAMES | VALUE |
|-------------------------------+-------------------+-------------+----------------+------------------+-------|
| 2025-09-02 21:40:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | [ | 4124 |
| | | | "COLUMN" | "LAST_UPDATED" | |
| | | | ] | ] | |
| 2025-09-02 21:25:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 21:20:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | [ | 2924 |
| | | | "COLUMN" | "LAST_UPDATED" | |
| | | | ] | ] | |
| 2025-09-02 21:20:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 21:15:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 21:15:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | [ | 2624 |
| | | | "COLUMN" | "LAST_UPDATED" | |
| | | | ] | ] | |
| 2025-09-02 21:10:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 21:05:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 21:05:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | [ | 2024 |
| | | | "COLUMN" | "LAST_UPDATED" | |
| | | | ] | ] | |
| 2025-09-02 21:00:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | [ | 1724 |
| | | | "COLUMN" | "LAST_UPDATED" | |
| | | | ] | ] | |
| 2025-09-02 21:00:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 20:55:00.000 +0900 | SAMPLE_DATA_TABLE | FRESHNESS | [ | [ | 1424 |
| | | | "COLUMN" | "LAST_UPDATED" | |
| | | | ] | ] | |
| 2025-09-02 20:55:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 20:50:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 0 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 20:45:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 1 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
| 2025-09-02 20:40:00.000 +0900 | SAMPLE_DATA_TABLE | NULL_COUNT | [ | [ | 1 |
| | | | "COLUMN" | "ID" | |
| | | | ] | ] | |
+-------------------------------+-------------------+-------------+----------------+------------------+-------+
さいごに
DMF をオブジェクトに割り当てる際設定できる expectations(期待値)を試してみました。
判定ロジックと結果までビューで確認できるのは便利と思いました。
こちらの内容が何かの参考になれば幸いです。