「履歴が見えない?」ACCOUNT_USAGEとINFORMATION_SCHEMAの違いとRBAC
🚀 はじめに
Snowflake を使い始めた頃、
「先月のクエリ履歴が見たいな」
と思って INFORMATION_SCHEMA.QUERY_HISTORY を叩いたら、
なぜか7日分しか見られなくて 焦った...
こんな経験、ありませんか?
あるいは、
「今、このデータベースにどんなテーブルがあるか一覧が欲しい」
と思って ACCOUNT_USAGE.TABLES を見たら、
情報が古くて困った...
という逆のパターンもあるかもしれません。
Snowflake には、アカウントやデータベースの「メタデータ(情報についての情報)」を格納したスキーマが2種類用意されています。
それが、ACCOUNT_USAGE と INFORMATION_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 ビューに反映されます。
その代わり、履歴データの保持期間は非常に短いか、「現在の状態」のみを保持します。
-
TABLESやCOLUMNSビュー:- 今存在するオブジェクトの定義情報(メタデータ)のみ。過去の情報(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)
- 過去3ヶ月で最も重かったクエリは? (
-
監査・ガバナンス:
- 誰がどのテーブルにアクセスしたか? (
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_DB の USERS テーブルのカラム名を全部取得して、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_HISTORYやSTORAGE_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に継承させるだけです。
- もし営業分析チームが別のスキーマも見る必要が出たら、新しい AR を作り、それを
-
最小権限の原則:
- ユーザーは自分の職務に必要な権限(FR)しか持たず、個別のテーブル権限(AR)を直接操作することはありません。
😌 おわりに
INFORMATION_SCHEMA と ACCOUNT_USAGE の使い分け、そして ACCOUNT_USAGE の安全な管理方法について、ご理解いただけたでしょうか?
-
INFORMATION_SCHEMA: 「今・ここ」の参照に使う。リアルタイムだが短期(7日間/14日間)。 -
ACCOUNT_USAGE: 「過去・全体」の監査に使う。長期(1年間)だが遅延あり(最大2時間程度、ビューによる)。 -
権限管理:
ACCOUNT_USAGEは機密情報の宝庫。アクセスは専用ロールを作成し、SNOWFLAKEデータベースロール(例:USAGE_VIEWER=コスト,GOVERNANCE_VIEWER=監査/クエリ履歴)を使って最小権限を付与する。 - ロール設計: 日常の権限管理は「アクセスロール(AR)と機能ロール(FR)の分離」を徹底する。
(補足:複数のアカウントを束ねてコスト等を分析したい場合は、ORGANIZATION_USAGE というスキーマも存在します。)
これらの原則を守ることで、Snowflake の強力なメタデータ機能を、安全かつ効率的に活用することができます。
📚 参考出典
- Snowflake公式: Account Usage
- Snowflake公式: Information Schema
- Snowflake公式: QUERY_HISTORY (Information Schema) テーブル関数 (※7日間の制約)
- Snowflake公式: COPY_HISTORY (Information Schema) テーブル関数 (※14日間の制約)
- Snowflake公式: QUERY_HISTORY (Account Usage) ビュー (※1年間の保持, 遅延注記)
- Snowflake公式: ACCESS_HISTORY (Account Usage) ビュー (※1年間の保持)
- Snowflake公式: COPY_HISTORY (Account Usage) ビュー (※1年間の保持、遅延)
- Snowflake公式: ロールベースのアクセスコントロール (RBAC)
Discussion