SELECTSELECT

SELECT

Snowflakeオブジェクトタグで実現するデータガバナンス

By Jeff SkoldbergJun 23, 202512 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

Snowflakeのオブジェクトタグとは

Snowflakeのオブジェクトタグは、オブジェクト(ウェアハウス、テーブルなど)を分類・グルーピングするためのデータガバナンス機能です。検索性を高め、利用状況を把握し、Snowflakeオブジェクトのコンプライアンス遵守状況をモニタリングすることを目的としています。タグは、PIIや財務データといった機密情報を含むSnowflakeオブジェクトを識別するのに特に役立ちます。また、リソースの所有者の割り当てや、コスト管理・データガバナンスの観点でも有効です。

タグとは

Snowflakeでオブジェクトにタグを付けるには、まずタグそのものを作成する必要があります。

タグはSnowflakeのスキーマレベルのオブジェクトで、データベース、スキーマ、テーブル、カラム、ユーザー、ウェアハウス、ロールなど、ほかのSnowflakeオブジェクトに付与できます。タグ付け可能なオブジェクトはかなり幅広く、一覧はこちらで確認できます。

タグはキーと値のペアです。タグ名(create tag <tag name>)が「キー」に相当し、値は事前に許可リストを定義することも、任意の文字列を許容するように制限なしにすることもできます。

たとえば、特定のテーブルの利用部門を把握したい場合、「audience」というタグ(キー)を作り、値をHR、Sales、Operations、ITなどに設定できます。こうしたタグは「営業が使っているテーブルをすべて表示」といった検索で簡単にクエリできます。詳しくは本記事の後半で扱います。

タグの継承

ここで、Snowflakeの「コンテナ階層」を簡単におさらいしておきましょう。Snowflake Organizationはアカウントを格納するコンテナで、アカウントはデータベースを、データベースはスキーマを格納します。そしてスキーマは、テーブル、ビュー、パイプ、ファイルフォーマット、ステージなど、多くのオブジェクトを格納するコンテナです。

コンテナ階層のどこかでオブジェクトにタグを付けると、そのタグは下位のすべてのオブジェクトへと引き継がれます。たとえばデータベースにタグを付ければ、配下のテーブル、ビュー、カラム、さらにはパイプやステージといったオブジェクトもすべて、そのデータベースのタグを継承します。

たとえば、アカウント・データベース・スキーマの各レベルで明示的にタグを設定しているとしましょう。

{
  "account": {
    "tags": {
      "env": "prod",
      "region": "us-east-1"
    },
    "databases": {
      "analytics": {
        "tags": {
          "owner": "data_team",
          "classification": "restricted"
        },
        "schemas": {
          "sales": {
            "tags": {

Expand Code

regionはアカウントレベルで設定されているので、配下のすべてのデータベース、スキーマ、テーブル、ビュー、そしてすべてのカラムがus-east-1という値を継承します。便利ですよね。

タグの系統はsnowflake.account_usage.tag_references_with_lineage関数で簡単にクエリできます。詳しくは後述の「SQLでタグを確認する」をご覧ください。

オブジェクトタグとクエリタグの違い

Snowflakeにおけるクエリタグは、クエリやセッションに紐づける単一の文字列で、クエリ履歴のフィルタリングや検索を容易にします。クエリタグはキーと値のペアではなく、検索可能な単なる文字列です。一方のオブジェクトタグはキーと値のペアで、Snowflakeのデータガバナンスフレームワークの一部に位置付けられています。テーブル、カラム、スキーマといったデータ資産へのアクセスを分類・制御・監査するために使います。

Snowflakeで「タグ付け」という言葉が出てきたら、それがクエリタグオブジェクトタグのどちらを指しているのかを必ず確認しましょう。両者は用途がまったく異なります。

Snowflakeでのタグの使い方

タグを作成する

タグの作成構文は非常にシンプルです。create tag <tag_name> <allowed values>;

タグはスキーマレベルのオブジェクトなので、完全修飾名で書くか、ワークシートのコンテキストに注意してください。Snowflakeの他のオブジェクトと同様、タグもあるデータベース(またはスキーマ)で作成して、別のデータベースで利用できます。

例:

use schema governance.tags;
create tag table_classification allowed_values 'metadata', 'fact', 'dimension';
-- 許可される値のリストを指定してタグを作成します。

create tag user_group;
-- 任意の値を許可するタグを作成します。

許可される値を指定せずにタグを作成すると、allowed_valuesパラメータはnullになり、任意の文字列を値として設定できるようになります。値のリストを動的に扱いたい場合には便利ですが、多くのケースでは事前に許可値をリストアップしておき、必要に応じてalterで許可値を追加するのが一般的です。

タグの許可値を確認する

既存のタグの許可値を確認する方法はいくつかあります。

show tags;コマンドを実行すると、アカウント内のすべてのタグのメタデータが表示され、返される列のひとつにallowed_valuesが含まれます。

もうひとつは、特定のタグに対してシステム関数system$get_tag_allowed_valuesを呼び出す方法です。

select system$get_tag_allowed_values(
    'governance.tags.cost_center');

さらにもうひとつ、Snowflakeのget_ddl関数を呼び出す方法もあります。例:

1select get_ddl('tag','dev.public.TESTING_TAG_1');

オブジェクトにタグを付けて使う

オブジェクトにタグを設定するには、alterコマンドを使います。たとえばselect_blog.workday.workday_usersというテーブルにタグを設定する場合:

alter table select_blog.workday.workday_users
set tag tutorial_db.public.table_classification = 'metadata';

この例では、タグはtutorial_dbというデータベースで作成し、select_blogというデータベースで利用しています。

SQLでSnowflakeタグを確認する

方法1:account_usage.tag_referencesビューをクエリする

snowflake.account_usage.tag_referencesビューでは、タグが使われている場所とその値をすべて確認できます。フィルタリングによく使う列はtag_nametag_valueです。なお、このビューにタグの継承は反映されず、直接タグ付けされたオブジェクトのみが表示されます。

SELECT * FROM
snowflake.account_usage.tag_references
where tag_name ilike 'table_class%'
or tag_value ilike 'meta%'
ORDER BY TAG_NAME, DOMAIN, OBJECT_ID;

ただし、このビューのデータには大きな遅延がある点に注意してください。Snowflakeのドキュメントでは最大2時間遅れる可能性があるとされており、筆者の経験上もほとんどの場合で少なくとも1時間は遅れます。

方法2:get_tag関数

snowflake.account_usage.tag_referencesビューには遅延があるため、タグ付きオブジェクトの変更をすぐに確認したい場合もあるはずです。システム関数system$get_tagは常に最新の状態を返します。

構文:

SELECT SYSTEM$GET_TAG( <fully qualified tag name>,
<'fully qualified object name'>, <'object class such as table, view, etc' > )
AS TAG_META;

例:

SELECT SYSTEM$GET_TAG( 'tutorial_db.public.table_classification',
'SELECT_BLOG.WORKDAY.WORKDAY_USERS', 'TABLE' )
AS TAG_META;

方法3:account_usage.tag_lineage関数

先ほど触れた「タグの継承」では、タグが上位レベルから下位レベルへ自動的に引き継がれます。tag_lineage関数を使えば、直接タグ付けされたオブジェクトと、タグを継承したオブジェクトをまとめて確認できます。先ほどのtable_classificationの例の続きとして、次のようなSQLが書けます。

SELECT *
FROM TABLE(
  snowflake.account_usage.tag_references_with_lineage(
    'TUTORIAL_DB.PUBLIC.TABLE_CLASSIFICATION'
  )
);

結果から、WORKDAY_USERSテーブルに手動でタグが設定され、その配下のすべてのカラムがタグを継承していることがわかります。

このスクリーンショットでは、画面に収めるためにSnowsight UIで多くのカラムを非表示にしています。

Snowsight UIでSnowflakeタグを確認する

SnowflakeにはSnowflake内のすべてのタグを一覧できる便利なダッシュボードが用意されています。

accountadminロール、またはダッシュボードを表示できるよう適切に構成されたロールでSnowsightを開き、サイドバーから「Monitoring」→「Governance」へ移動します。

ダッシュボードの画面は以下のようになります。筆者はデモアカウントを使っているためタグは設定されていませんが、有用さは十分に伝わるはずです。

「Tagged Objects」タブをクリックすると、アカウント内のすべてのテーブルとビュー、そしてそれらに付与されているタグを確認できます。タグの有無にかかわらずオブジェクトが一覧表示されます。残念ながら、ユーザーやウェアハウスといったオブジェクトはここには表示されません。このページにはSnowflakeの豊富なフィルタリング機能が用意されているので、ぜひ各フィルタを試してみてください。

タグが付いているオブジェクトだけを表示したい場合は、「has tags」フィルタを有効にしましょう。

Snowflakeタグ運用のベストプラクティス

一元化されたタグポリシーを策定する

データガバナンス、特にPIIや機密データの管理は一筋縄ではいきません。多くは技術というよりも、議論と合意形成が中心となる仕事です。

最初のステップは、しっかり練られた戦略を持つことです。検討の出発点として、次のような問いがあります。

  • タグで何を実現したいのか?(コストレポート、機密データの保護など)
  • タグのリストと許可値は誰が定めるのか?(戦略)
  • どのロールがタグを設定でき、そのロールは誰に付与するのか?(戦術)
  • タグの継承をどう活用すれば最大の効果が得られるか?

タグの「許可値」を活用する

特にタグを手動で設定するケースでは、「allowed values」設定を積極的に活用しましょう。テーブルのデータをもとにタグを自動付与する場合は、それほど重要ではありません。

可能な限りタグ付けを自動化する

タグ付けを手動運用に頼ると、たいてい長続きしません。タグ付けを自動化する工夫を凝らしましょう。具体例はこの後で紹介します。

可能な限りデータパイプラインに組み込む

便利なdbtパッケージにdbt_tagsがあります。このパッケージはSnowflakeのオブジェクトタグ付けを自動化し、タグに基づく動的マスキングと連動させるのに役立ちます。タグベースでのデータマスキングを行いたい方は、ぜひチェックしてみてください。

タグの利用状況を継続的に監視・監査する

せっかくタグを作っても、見直さなければ意味がありません。月に1時間でよいので、タグ、利用状況、タグポリシーの見直しに時間を割きましょう。

Snowflakeタグ付けの自動化——実践例

シナリオ

Workday(または任意のERP)で従業員のメタデータを管理しており、そのテーブルがSnowflakeにETLされているシナリオを考えてみましょう。これをworkday_usersテーブルと呼びます。ユーザー1人につき1行があり、各カラムはSnowflakeユーザーのタグとして保持したい属性を表します。これにより、同じタグを持つユーザーの監査・状況確認・権限設定が可能になります。

ユーザーの部門や職務が変わったら、Snowflakeのタグも自動的に更新されるようにします。

モックデータを用意する

このシナリオ用のテーブルとモックデータを作成しましょう。

-- このテーブルは、WorkdayからSnowflakeにETLされ、ユーザーのメタデータを保持するテーブルを表します
-- デモ用のデータベースを使っています。ご自身の環境に合わせて変更してください。
create or replace table select_blog.workday.workday_users
(
employee_id text,
work_email text,
manger_email text,
is_manager boolean,
pillar_id text,
group_id text,
team_id text,
department_id text,
job_family_id text,
area text,
cost_center text,

Expand Code

テーブルにモックデータを投入します。

1insert into select_blog.workday.workday_users

2values(

33000,

4'[email protected]',

5null,

6true,

7'Pillar-C-SUITE',

8'Group-C-SUITE',

9'Team-Founders',

10'Department-All',

11'JF-Founders',

12'Founders',

13'CC Board of Directors',

14'CC3625'

15),

Expand Code

このシナリオでは、末尾が_idで終わるフィールドをすべてSnowflakeユーザーのタグへ変換することを目指します。

タグを作成する

workday_usersのカラム数は比較的安定していると仮定し、タグの作成は一度きり(または頻度の低い)作業として、自動化までは不要としましょう。カラムが追加されたら新しいタグを作成すれば済みます。(もちろん、以下のコードをタスクとしてスケジュール実行することも可能です。その場合は、タグを「replace」しないようにご注意ください。)

以下のコードはカラムのメタデータをクエリし、要件どおり_idを含むカラムだけに絞り込みます。これらのカラム名がそのままタグ名になります。各_idカラムについて、新しいタグを作成するだけです。今回は値をデータから設定するため、許可値は事前に定義しません。

このコードを使えば、十数件ものcreate tag文を手で書く必要がなくなります。select文の各行に対してcreate or replace tag ...を実行します。

BEGIN
    -- 変数を宣言
    LET create_tag_statements RESULTSET := (
        SELECT
            'CREATE OR REPLACE TAG "' || COLUMN_NAME || '" COMMENT = ''Tag for ' || COLUMN_NAME || ''';' AS create_tag_statement
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'WORKDAY_USERS'
          AND TABLE_SCHEMA = 'WORKDAY'
          AND LOWER(COLUMN_NAME) ILIKE '%_ID'
    );

    -- 結果セットをループして各ステートメントを実行
    LET stmt VARCHAR DEFAULT '';
    LET create_tag_cursor CURSOR FOR SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));

Expand Code

あるいは、次のようなコマンドを手動で実行することもできます。

use schema select_blog.workday;
create tag pillar_id;
create tag team_id;

-- 不要になったタグは削除
drop tag my_obsolete_tag;

実際のユーザータグと「あるべき状態」を比較するビューを作成する

workday_usersテーブルは、ユーザータグをどう設定すべきかについてWorkdayから取得した最新情報を保持しており、これが「あるべき状態」となります。次に、実際のユーザータグをこの「あるべき状態」と突き合わせ、タグが正しく設定されていない行を抽出します。(ここでは、workday_usersテーブルのwork_emailカラムがsnowflake.account_usage.usersテーブル上のSnowflakeユーザーのメールアドレスに対応していると見なせます。)

このクエリは何度も使い回すので、ビューとして保存しておきましょう。

create or replace view tag_updates as
with desired_tags as (
    select
        upper(work_email) as user_email,
        upper(tag_name) as tag_name,
        replace(upper(desired_tag_value), '-', '_') as desired_tag_value,
    from
        workday_users unpivot (
            desired_tag_value for tag_name in (pillar_id, group_id, group_id)
        )
),

snowflake_user_email as (
    select
        upper(name) as user_name,

Expand Code

このビューの処理内容をまとめると次のとおりです。

  • workdayテーブルをアンピボット(カラムを行に展開)し、ユーザーとタグ候補の組み合わせごとに1行を生成します。
  • タグを付ける対象のSnowflake USER_NAMEと、「あるべき状態」テーブルと結合するためのSnowflake側のメールアドレスを取得します。
  • メールアドレスをキーに結合し、各ユーザーの既存タグを取得します。
  • 最後に、既存のタグ値があるべきタグ値と一致しないレコードをすべて表示します。

ここで抽出されたレコードが、ストアドプロシージャで自動的に設定すべき対象です。

tag_updatesビューは既存タグの値が「あるべき値」と一致しない行に絞り込まれているため、タグが正しく設定されていれば、理想的にはこのビューは空になります。

ユーザーにタグを設定するストアドプロシージャを作成する

ストアドプロシージャの基本的なステップは次のとおりです。

  • tag_updatesビューの各行について:
    • alter userを実行し、タグをあるべき値に設定する

以下では、2バージョンのストアドプロシージャを用意しました。1つ目はログ出力のないシンプル版で、見通しがよく読みやすい構成です。2つ目はより詳しく、想定どおりにタグが設定されない場合のトラブルシューティング向けで、SQL結果ペインに出力メッセージを表示します。

シンプル版:

CREATE OR REPLACE PROCEDURE SET_USER_TAGS()
  RETURNS VARCHAR
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.8'
  PACKAGES = ('snowflake-snowpark-python')
  HANDLER = 'main'
AS
$$
def main(session):
    query = """
      SELECT
        user_name as USER_NAME,
        tag_name as TAG_NAME,
        desired_tag_value as DESIRED_TAG_VALUE
      FROM tag_updates

Expand Code

ログ出力付きの詳細版:

-- 「alter user」権限を持つ管理ロールでプロシージャを作成します。
user role accountadmin; -- またはユーザーが実際にuseradminによって所有されている場合はuseradminロールを使用
-- useradminロールを使う場合は、対象データベースに対してUSAGEをそのロールに付与する必要があるため、accountadminを使う方が簡単です。
CREATE OR REPLACE PROCEDURE SET_USER_TAGS()
  RETURNS VARCHAR
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.8'
  PACKAGES = ('snowflake-snowpark-python')
  HANDLER = 'main'
AS
$$
def main(session):
    # 改訂したビューから必要なカラムだけを取得
    query = """
      SELECT

Expand Code

プロシージャを呼び出します。

1call set_user_tags();

あとはランチでも取りつつ、account_usage.tag_referencesビューが更新されるまで1時間ほど(場合によってはそれ以上)待ちましょう。タグが正しく設定され、ビューも更新されていれば、select * from tag_updates;は何も返さないはずです。まさに狙いどおりの結果です。

ストアドプロシージャをスケジュール実行するタスクを作成する

このタスクは毎日UTC午前4時にプロシージャを実行します。

CREATE TASK set_user_tags
SCHEDULE = 'USING CRON 0 4 * * * UTC' AS
CALL set_user_tags();
alter task set_user_tags resume;

これで、Workdayのメタデータテーブルに基づいてユーザータグを自動更新する仕組みが完成しました。

次はあなたの番です

本例で取り上げたのは、タグ自動化のひとつのシナリオに過ぎません。ただし、タグ運用のベストプラクティスに沿って、可能な限りタグ付けの自動化を目指してください。プロセスはいずれの場合も同じです。

  • 「あるべき状態」を定義する。
  • タグを作成する(手動でも自動でも構いません)。
  • あるべき状態と現状を比較して、タグ設定を自動化する。

まとめ

本記事では、Snowflakeにおけるタグの用途、タグの作成方法、ベストプラクティス、そして応用シナリオを紹介しました。ぜひ工夫を凝らして、ご自身のSnowflakeアカウントでタグ付けを自動化する方法を考えてみてください。

Jeffはデータ・アナリティクスのコンサルタントで、インサイトの自動化やデータを活用した業務プロセスの制御に15年以上携わってきました。技術面ではSnowflake + dbt + Tableauを得意とし、業務領域では公共事業、臨床試験、出版、CPG、製造業での経験があります。お気軽にご連絡ください:[email protected]