❄️

「履歴が見えない?」ACCOUNT_USAGEとINFORMATION_SCHEMAの違いとRBAC

に公開

🚀 はじめに

Snowflake を使い始めた頃、
「先月のクエリ履歴が見たいな」
と思って INFORMATION_SCHEMA.QUERY_HISTORY を叩いたら、
なぜか7日分しか見られなくて 焦った...

こんな経験、ありませんか?

あるいは、
「今、このデータベースにどんなテーブルがあるか一覧が欲しい」
と思って ACCOUNT_USAGE.TABLES を見たら、
情報が古くて困った...

という逆のパターンもあるかもしれません。

Snowflake には、アカウントやデータベースの「メタデータ(情報についての情報)」を格納したスキーマが2種類用意されています。
それが、ACCOUNT_USAGEINFORMATION_SCHEMA です。

これらは似ているようで、実は目的も、見える範囲も、鮮度も、まったく違います
そして、特に ACCOUNT_USAGE へのアクセス許可には、重大なセキュリティリスク が伴います。

この記事では、この2つのスキーマの違いから、ACCOUNT_USAGE に潜むリスク、そしてそのリスクを管理するための安全な権限設定(RBAC)のベストプラクティスまでを、一気通貫で解説します。

🗺️ 1. INFORMATION_SCHEMA:「今・ここ」を参照するスキーマ

Snowflake Information Schema(以下、INFORMATION_SCHEMA)は、各アカウント内の各データベースに自動的に存在するスキーマです。
MY_DB.INFORMATION_SCHEMA, SNOWFLAKE_SAMPLE_DATA.INFORMATION_SCHEMA のように、どこにでもあります)

特徴:リアルタイム、だが短期 or 現在のみ

INFORMATION_SCHEMA の最大の特徴は、ほぼリアルタイムであることです。
CREATE TABLE を実行したら、即座に INFORMATION_SCHEMA.TABLES ビューに反映されます。

その代わり、履歴データの保持期間は非常に短いか、「現在の状態」のみを保持します。

  • TABLESCOLUMNS ビュー:
    • 存在するオブジェクトの定義情報(メタデータ)のみ。過去の情報(DROPされたテーブルなど)は保持しません。
  • QUERY_HISTORY (テーブル関数):
    • 履歴情報ですが、保持期間は過去7日間です。
  • COPY_HISTORY (テーブル関数):
    • データロードの履歴です。保持期間は過去14日間です。

主なユースケース:「今」と「メタデータ」

  • オブジェクトの探索:
    • このデータベースに STG_ で始まるテーブルは何がある? ( TABLES )
    • USERS テーブルのカラム一覧とデータ型は? ( COLUMNS )
  • 動的SQLの生成:
    • _TEMP スキーマの全テーブルに TRUNCATE を実行する、といった管理タスク用のSQLを自動生成する。
  • 直近の履歴確認:
    • さっき実行したコピー(ロード)処理の結果は? ( TABLE(INFORMATION_SCHEMA.COPY_HISTORY(...)) )

📒 2. ACCOUNT_USAGE:「過去・全体」を監査するスキーマ

ACCOUNT_USAGE は、SNOWFLAKE データベース(Snowflake が自動で提供する読み取り専用DB)の中に存在するスキーマです。

特徴:遅延あり、だが長期保持

ACCOUNT_USAGE の最大の特徴は、アカウント全体の履歴情報1年間 という長期間保持してくれることです(例: QUERY_HISTORY, ACCESS_HISTORY)。

その代わり、データはリアルタイムではありません
Account Usage の多くのビューは通常 45 分以内に反映されますが、ビューによっては最大2時間程度の遅延が発生することもあります。直後のトラブルシュートには Information Schema(リアルタイム/短期保持)を、長期分析には Account Usage(長期保持/遅延あり)を使い分けましょう。

主なユースケース:「過去」と「コスト」と「監査」

  • コスト監視:
    • 先月のウェアハウスごとのクレジット消費は? ( WAREHOUSE_METERING_HISTORY )
  • パフォーマンス分析:
    • 過去3ヶ月で最も重かったクエリは? ( QUERY_HISTORY )
  • 監査・ガバナンス:
    • 誰がどのテーブルにアクセスしたか? ( ACCESS_HISTORY ※Enterprise版以上)
    • ログイン履歴は? ( LOGIN_HISTORY )

🎯 3. 徹底比較:どっちを使うべき?

2つのスキーマの違いを整理します。目的が全く違うことがわかりますね。

  • INFORMATION_SCHEMA = 「今・ここ」(リアルタイム・短期)
  • ACCOUNT_USAGE = 「過去・全体」(遅延あり・長期)
比較軸 ACCOUNT_USAGE (SNOWFLAKE DB内) INFORMATION_SCHEMA (各DB内)
主な目的 監査 (Audit) & コスト分析 参照 (Reference) & 探索
データの範囲 アカウント全体 特定のデータベース内
データの鮮度 遅延あり (最大 2 時間程度、ビューによる) ほぼリアルタイム
データ保持期間 長い (例: 1年間) 短い (例: 7日間/14日間 or 現在のみ)
必要な権限 SNOWFLAKE データベースロール (例: USAGE_VIEWER, GOVERNANCE_VIEWER) ※付与作業はACCOUNTADMIN 対象 DB/スキーマ/オブジェクトへの USAGE/SELECT 等の一般的な権限

シナリオ別:使い分けクイズ

Q1: 「MY_DBUSERS テーブルのカラム名を全部取得して、SELECT文を動的に作りたい」
A1: MY_DB.INFORMATION_SCHEMA.COLUMNS

  • 理由: 「今現在」のテーブル定義(メタデータ)がリアルタイムで必要なため。ACCOUNT_USAGE.COLUMNS は遅延があり、最新の定義変更が反映されていない可能性があります。

Q2: 「今月、最もストレージを消費しているテーブル TOP10 は?」
A2: ACCOUNT_USAGE.TABLE_STORAGE_METRICS

  • 理由: 「ストレージ消費」というコスト関連の情報であり、アカウント全体の集計が必要なためです。

Q3: 「さっき実行した COPY INTO が失敗した。エラー理由は?」
A3: TABLE(MY_DB.INFORMATION_SCHEMA.COPY_HISTORY(...))

  • 理由: 直後のデバッグには INFORMATION_SCHEMA.COPY_HISTORY(14日間・ほぼリアルタイム)を使います。長期の傾向分析には ACCOUNT_USAGE.COPY_HISTORY ビュー(1年間保持・遅延あり)を使います。

Q4: 「先週の金曜日に実行された、特定のウェアハウスでのクエリ実行時間は?」
A4: ACCOUNT_USAGE.QUERY_HISTORY

  • 理由: 「先週」という過去の情報を、「1年間」保持している ACCOUNT_USAGE から引く必要があります。INFORMATION_SCHEMA.QUERY_HISTORY (テーブル関数) は過去7日間までしか遡れません。

🛠️ 実用スニペット:使い分けの具体例

例1:直近14日間のコピー失敗を「即時」デバッグ(Information Schema)

SELECT *
FROM TABLE(MY_DB.INFORMATION_SCHEMA.COPY_HISTORY(
  table_name=>'MY_SCHEMA.MY_TABLE',
  start_time=>DATEADD('day', -14, CURRENT_TIMESTAMP())
))
WHERE error_count > 0
ORDER BY last_load_time DESC;

例2:先週金曜のクエリ傾向を「長期」分析(Account Usage)

SELECT user_name, warehouse_name, total_elapsed_time, query_text
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
WHERE start_time BETWEEN '2025-10-31 00:00:00' AND '2025-11-01 00:00:00'
ORDER BY total_elapsed_time DESC
LIMIT 50;

⚠️ 4. ACCOUNT_USAGE アクセスの重大なリスク

Q2 や Q4 のような分析をするために、ACCOUNT_USAGE スキーマへのアクセスが必要になることがあります。

しかし、ACCOUNTADMIN 以外のロールで参照しようとすると、デフォルトでは見ることができません。
このアクセス許可の設定を誤ると、重大なセキュリティリスクにつながります。

ACCOUNT_USAGE はアカウントの「監査ログ」そのものです。このスキーマへのアクセスを許可すると、以下の機密情報が閲覧可能になります。

リスク1: アカウント全体の「コスト情報」

  • WAREHOUSE_METERING_HISTORYSTORAGE_USAGE など、アカウント全体の運用コストが丸見えになります。

リスク2: アカウント全体の「クエリ履歴」(過去1年分)

  • QUERY_HISTORY には、過去1年間に実行されたほぼすべてのSQLクエリが格納されています。
  • もし、ユーザーがクエリ内にパスワードや個人情報、APIキーなどをハードコーディングしていた場合、それらがすべて閲覧可能になってしまいます。

リスク3: アカウント全体の「監査ログ」(内部監査情報)

  • LOGIN_HISTORY (誰が、いつ、どこからログインしたか)
  • ACCESS_HISTORY (誰がどのデータにアクセスしたか)
  • これら内部監査レベルの情報が、一般の分析者にも見えてしまいます。

🔐 5. 安全な ACCOUNT_USAGE へのアクセス設定 (最小権限の原則)

ACCOUNTADMIN ロールを日常的に使うことなく、安全にコストやパフォーマンスを監視するにはどうすればよいでしょうか?

答えは、「目的を限定した専用のロールを作成し、そのロールに最小限の権限を付与する」です。

方法1(推奨):SNOWFLAKE データベースロールの活用

Snowflake は、ACCOUNT_USAGE 内のビューを用途別にグループ化した「データベースロール」を提供しています。
これを活用するのが、最も安全で推奨される方法です。

-- 1. ACCOUNTADMIN になる
USE ROLE ACCOUNTADMIN;

-- 2. コスト監視・監査用のカスタムロールを作成
CREATE ROLE IF NOT EXISTS COST_AUDIT_ROLE;

-- 3. 必要な SNOWFLAKE データベースロールをカスタムロールに付与
-- (目的別に最小権限を合成する)

-- コスト/使用量系 (例: WAREHOUSE_METERING_HISTORY)
GRANT DATABASE ROLE SNOWFLAKE.USAGE_VIEWER TO ROLE COST_AUDIT_ROLE;

-- クエリ履歴/アクセス監査 (例: QUERY_HISTORY, ACCESS_HISTORY)
GRANT DATABASE ROLE SNOWFLAKE.GOVERNANCE_VIEWER TO ROLE COST_AUDIT_ROLE;

-- ログイン監査 (例: LOGIN_HISTORY) (必要な場合)
GRANT DATABASE ROLE SNOWFLAKE.SECURITY_VIEWER TO ROLE COST_AUDIT_ROLE;

-- 4. このロールを、本当に必要なユーザー(例: 財務担当者、監査担当者)にのみ付与
GRANT ROLE COST_AUDIT_ROLE TO USER JANE_DOE;

方法2(非推奨):IMPORTED PRIVILEGES の利用

従来、以下の方法も使われてきました。

-- 【非推奨、または利用を厳格に限定すべき方法】
USE ROLE ACCOUNTADMIN;
CREATE ROLE IF NOT EXISTS LEGACY_MONITOR_ROLE;

-- (A) ACCOUNT_USAGE スキーマ自体へのアクセス権限
GRANT MONITOR USAGE ON ACCOUNT TO ROLE LEGACY_MONITOR_ROLE;

-- (B) SNOWFLAKE データベース(箱)へのアクセス権限
GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE LEGACY_MONITOR_ROLE;

✨ 6. 発展:Snowflake ロール設計のベストプラクティス (RBAC)

ACCOUNT_USAGE のような特殊なケース以外でも、日常的なロール設計には明確な「型」があります。
Snowflake が推奨するベストプラクティスは、「機能ロール」と「アクセスロール」を分離することです。

1. アクセスロール (Access Roles / AR)

  • 目的: 特定のデータベースオブジェクト(テーブルなど)への権限(例: SELECT)を定義する「権限セット」。
  • 例: AR_SALES_MART_SELECT
  • 特徴: このロールを直接ユーザーに付与しません

2. 機能ロール (Functional Roles / FR)

  • 目的: ユーザーの「職務」や「役割」(例: 営業分析者)を定義する。
  • 例: FR_SALES_ANALYST
  • 特徴: このロールをユーザーに付与します。

組み合わせ方(ロールの継承)

ユーザーには「機能ロール (FR)」だけを付与します。
そして、「機能ロール (FR)」が「アクセスロール (AR)」を継承します。

-- === ベストプラクティスの例 (SYSADMIN で実行) ===

-- 1. アクセスロール (AR) の作成 (オブジェクトへの権限)
CREATE ROLE AR_SALES_MART_SELECT;
GRANT USAGE ON DATABASE SALES_DB TO ROLE AR_SALES_MART_SELECT;
GRANT USAGE ON SCHEMA SALES_DB.MART TO ROLE AR_SALES_MART_SELECT;
GRANT SELECT ON ALL TABLES IN SCHEMA SALES_DB.MART TO ROLE AR_SALES_MART_SELECT;

-- (運用強化) 将来作成されるテーブルにも権限を付与
GRANT SELECT ON FUTURE TABLES IN SCHEMA SALES_DB.MART TO ROLE AR_SALES_MART_SELECT;

-- 2. 機能ロール (FR) の作成 (職務)
CREATE ROLE FR_SALES_ANALYST;

-- 3. 機能ロール (FR) が アクセスロール (AR) を継承する
GRANT ROLE AR_SALES_MART_SELECT TO ROLE FR_SALES_ANALYST;

-- 4. ユーザーに 機能ロール (FR) を付与する (USERADMIN や ACCOUNTADMIN で実行)
GRANT ROLE FR_SALES_ANALYST TO USER BOB_SMITH;

なぜこの設計が良いのか?

  • 管理がシンプル:
    • BOB_SMITH さんを営業分析チームに追加して」と言われたら、FR_SALES_ANALYST ロールを付与するだけで完了です。
  • 柔軟性が高い:
    • もし営業分析チームが別のスキーマも見る必要が出たら、新しい AR を作り、それを FR_SALES_ANALYST に継承させるだけです。
  • 最小権限の原則:
    • ユーザーは自分の職務に必要な権限(FR)しか持たず、個別のテーブル権限(AR)を直接操作することはありません。

😌 おわりに

INFORMATION_SCHEMAACCOUNT_USAGE の使い分け、そして ACCOUNT_USAGE の安全な管理方法について、ご理解いただけたでしょうか?

  • INFORMATION_SCHEMA: 「今・ここ」の参照に使う。リアルタイムだが短期(7日間/14日間)。
  • ACCOUNT_USAGE: 「過去・全体」の監査に使う。長期(1年間)だが遅延あり(最大2時間程度、ビューによる)。
  • 権限管理: ACCOUNT_USAGE は機密情報の宝庫。アクセスは専用ロールを作成し、SNOWFLAKE データベースロール(例: USAGE_VIEWER=コスト, GOVERNANCE_VIEWER=監査/クエリ履歴)を使って最小権限を付与する。
  • ロール設計: 日常の権限管理は「アクセスロール(AR)と機能ロール(FR)の分離」を徹底する。

(補足:複数のアカウントを束ねてコスト等を分析したい場合は、ORGANIZATION_USAGE というスキーマも存在します。)

これらの原則を守ることで、Snowflake の強力なメタデータ機能を、安全かつ効率的に活用することができます。

📚 参考出典

Discussion