Snowflake

Snowflake ACCESS_HISTORYで列レベル追跡

2026-03-26
更新: 2026-03-27
NicheeLab編集部

SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORYは、 Snowflakeアカウント内で実行されたすべてのクエリに対して、どのオブジェクトのどの列にアクセスしたかを列レベルで記録するビューです。 GDPR / CCPA / SOX法などのコンプライアンス要件に対応する監査証跡として、 またデータリネージュの追跡基盤として活用されます。Enterprise Edition以上で利用可能です。

ACCESS_HISTORYの構造

ACCESS_HISTORYビューには複数のSEMI-STRUCTURED列(ARRAY / OBJECT型)が含まれており、 それぞれ異なるレベルのアクセス情報を記録しています。

列名内容
query_idVARCHARクエリの一意識別子
query_start_timeTIMESTAMP_LTZクエリの実行開始時刻
user_nameVARCHARクエリを実行したユーザー
direct_objects_accessedARRAYクエリで直接参照されたオブジェクト(ビュー等含む)と列情報
base_objects_accessedARRAY最終的にアクセスされたベーステーブルと列情報
objects_modifiedARRAYINSERT/UPDATE/DELETE等で変更されたオブジェクトと列情報
object_modified_by_ddlOBJECTDDL操作(CREATE/ALTER/DROP等)の対象オブジェクト
policies_referencedARRAYアクセス時に評価されたポリシー(マスキング/行アクセス等)

direct_objects_accessed vs base_objects_accessed

-- 例: ビュー経由でテーブルにアクセスした場合
-- CREATE VIEW v_customers AS SELECT name, email FROM customers;
-- SELECT name FROM v_customers;

-- direct_objects_accessed の内容:
-- [{ "objectName": "V_CUSTOMERS",
--    "objectDomain": "View",
--    "columns": [{"columnName": "NAME"}] }]

-- base_objects_accessed の内容:
-- [{ "objectName": "CUSTOMERS",
--    "objectDomain": "Table",
--    "columns": [{"columnName": "NAME"}] }]

-- → ビュー V_CUSTOMERS を直接参照したが、
--   実際にアクセスされたベーステーブルは CUSTOMERS の NAME 列

READ操作の監査クエリ

-- 特定テーブルの列にアクセスしたユーザーと頻度を分析
SELECT
  ah.user_name,
  bo.value:objectName::STRING AS table_name,
  col.value:columnName::STRING AS column_name,
  COUNT(*) AS access_count,
  MIN(ah.query_start_time) AS first_access,
  MAX(ah.query_start_time) AS last_access
FROM SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY ah,
  LATERAL FLATTEN(input => ah.base_objects_accessed) bo,
  LATERAL FLATTEN(input => bo.value:columns) col
WHERE ah.query_start_time >= DATEADD(DAY, -30, CURRENT_TIMESTAMP())
  AND bo.value:objectName::STRING = 'CUSTOMERS'
GROUP BY 1, 2, 3
ORDER BY access_count DESC;

WRITE操作の監査クエリ

-- テーブルへのWRITE操作を追跡
SELECT
  ah.query_id,
  ah.user_name,
  ah.query_start_time,
  om.value:objectName::STRING AS modified_table,
  om.value:objectDomain::STRING AS object_type,
  col.value:columnName::STRING AS modified_column
FROM SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY ah,
  LATERAL FLATTEN(input => ah.objects_modified) om,
  LATERAL FLATTEN(input => om.value:columns) col
WHERE ah.query_start_time >= DATEADD(DAY, -7, CURRENT_TIMESTAMP())
  AND om.value:objectName::STRING = 'CUSTOMER_PII'
ORDER BY ah.query_start_time DESC;

policies_referenced による ポリシー監査

クエリ実行時にマスキングポリシーや行アクセスポリシーが評価された場合、policies_referenced列にポリシー名と種類が記録されます。 これにより「どのポリシーがどの頻度で適用されているか」を可視化できます。

-- マスキングポリシーの適用状況を分析
SELECT
  pol.value:policyName::STRING AS policy_name,
  pol.value:policyKind::STRING AS policy_kind,
  COUNT(DISTINCT ah.query_id) AS query_count,
  COUNT(DISTINCT ah.user_name) AS user_count
FROM SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY ah,
  LATERAL FLATTEN(input => ah.policies_referenced) pol
WHERE ah.query_start_time >= DATEADD(DAY, -30, CURRENT_TIMESTAMP())
GROUP BY 1, 2
ORDER BY query_count DESC;

データリネージュの構築

ACCESS_HISTORYのbase_objects_accessedobjects_modifiedを 組み合わせることで、「どのテーブルのデータがどのテーブルに流れたか」という データリネージュ(データ系譜)を構築できます。

-- データフロー(ソーステーブル → ターゲットテーブル)の可視化
SELECT
  bo.value:objectName::STRING AS source_table,
  om.value:objectName::STRING AS target_table,
  ah.user_name,
  COUNT(*) AS flow_count,
  MAX(ah.query_start_time) AS latest_flow
FROM SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY ah,
  LATERAL FLATTEN(input => ah.base_objects_accessed) bo,
  LATERAL FLATTEN(input => ah.objects_modified) om
WHERE ah.query_start_time >= DATEADD(DAY, -30, CURRENT_TIMESTAMP())
  AND ARRAY_SIZE(ah.objects_modified) > 0
GROUP BY 1, 2, 3
ORDER BY flow_count DESC;

機密列アクセスの検出

-- PII列(email, ssn, phone等)へのアクセスを検出
SELECT
  ah.user_name,
  bo.value:objectName::STRING AS table_name,
  col.value:columnName::STRING AS column_name,
  COUNT(*) AS access_count
FROM SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY ah,
  LATERAL FLATTEN(input => ah.base_objects_accessed) bo,
  LATERAL FLATTEN(input => bo.value:columns) col
WHERE ah.query_start_time >= DATEADD(DAY, -7, CURRENT_TIMESTAMP())
  AND col.value:columnName::STRING IN ('EMAIL', 'SSN', 'PHONE_NUMBER', 'CREDIT_CARD')
GROUP BY 1, 2, 3
ORDER BY access_count DESC;

ユースケースまとめ

ユースケース使用する列対象規制・要件
PII列へのアクセス監査base_objects_accessed → columnsGDPR / CCPA
データリネージュ追跡base_objects_accessed + objects_modifiedSOX法 / 内部統制
マスキングポリシー適用監査policies_referencedセキュリティポリシー準拠
不使用テーブル/列の検出base_objects_accessed(アクセスなし列の特定)コスト最適化
データ変更の監査証跡objects_modified → columnsHIPAA / 金融規制

ベストプラクティス

  • LATERAL FLATTENでARRAY列をリレーショナルに展開:base_objects_accessedやpolicies_referencedはARRAY型のため、LATERAL FLATTENで行に展開してから集計する
  • 日次の監査レポートをTaskで自動生成:PII列へのアクセスサマリーをTaskで定期集計し、異常検出時にアラートを発報する
  • Tag-based Maskingとの連携:タグで機密列を分類し、ACCESS_HISTORYのpolicies_referencedでポリシー適用状況を監査する
  • ドロップ済みオブジェクトの追跡にも有効:ACCOUNT_USAGEは365日間の履歴を保持するため、すでにドロップされたテーブルへの過去のアクセスも追跡可能

問題で確認

Security & Governance

問題 1

GDPRコンプライアンス監査のため、過去30日間にCUSTOMERSテーブルのEMAIL列に直接またはビュー経由でアクセスしたすべてのユーザーを特定する必要がある。最も適切なアプローチはどれか。

  1. INFORMATION_SCHEMA.QUERY_HISTORYからSELECT文のquery_textをLIKE '%EMAIL%'で検索する
  2. ACCESS_HISTORYのdirect_objects_accessedをFLATTENして列名がEMAILのレコードを抽出する
  3. ACCESS_HISTORYのbase_objects_accessedをFLATTENしてCUSTOMERSテーブルのEMAIL列へのアクセスを抽出する
  4. LOGIN_HISTORYでCUSTOMERSテーブルにアクセスしたユーザーのログイン履歴を確認する

正解: C

ビュー経由のアクセスも含めて実際のベーステーブルのEMAIL列にアクセスしたユーザーを特定するには、base_objects_accessedを使う必要があります。direct_objects_accessedではビュー名が記録されるため、ベーステーブルの列レベル追跡には適しません。Aのquery_textのテキスト検索は列名が他のコンテキストで出現する可能性があり正確性に欠けます。DのLOGIN_HISTORYはログイン情報のみでデータアクセスの詳細は含みません。

よくある質問

ACCESS_HISTORYのbase_objects_accessedとdirect_objects_accessedの違いは何ですか?

direct_objects_accessedはクエリのFROM句で直接参照されたオブジェクト(ビュー、Dynamic Tableなど)を記録します。base_objects_accessedはそのオブジェクトが内部的にアクセスした実体テーブル(ベーステーブル)を記録します。たとえばビューVを経由してテーブルTのデータを読み取った場合、direct_objects_accessedにはVが、base_objects_accessedにはTが記録されます。データリネージュ追跡やセキュリティ監査ではbase_objects_accessedを使うことで、ビューの背後にある実際のデータアクセスを可視化できます。

ACCESS_HISTORYはEnterprise Edition以上が必要ですか?

はい、ACCESS_HISTORYビューはEnterprise Edition以上で利用可能です。Standard Editionではこのビューにアクセスできません。列レベルのデータアクセス追跡は高度なガバナンス機能であり、GDPRやSOX法などのコンプライアンス要件がある組織ではEnterprise以上のEditionを選択する必要があります。なお、ACCESS_HISTORYビューへのアクセスにはSNOWFLAKEデータベースのIMPORTED PRIVILEGESが必要です。

ACCESS_HISTORYでWRITE操作(INSERT/UPDATE/DELETE)も追跡できますか?

はい、ACCESS_HISTORYはREAD操作だけでなくWRITE操作も追跡します。objects_modified列にINSERT / UPDATE / DELETE / MERGE等で変更されたオブジェクトの情報が記録されます。これにより「誰がいつどのテーブルのどの列にデータを書き込んだか」を追跡でき、データ変更の監査証跡として活用できます。columns配列にはアクセスされた列名のリストが含まれるため、列レベルのWRITE監査も実現可能です。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Snowflake

Snowflake資格一覧|全11試験(SnowPro)の難易度・費用

Snowflake認定資格(SnowPro)全11試験の一覧・難易度・費用・出題範囲を徹底解説。...

Snowflake

Snowflake試験の難易度ランキング|全11資格を徹底比較

Snowflake(SnowPro)認定全11試験の難易度をランキング形式で比較。学習時間・合格に必要なスキルから分析。...

Snowflake

Snowflake資格の勉強方法|効率的な学習ルートと合格のコツ

Snowflake認定資格(SnowPro)に最短で合格するための勉強方法。公式リソース・学習スケジュールを徹底ガイド。...

Snowflake

SnowPro Core試験完全解説|出題範囲・問題例・合格戦略

SnowPro Core Certification(COF-C03)を徹底解説。出題範囲・100問の試験形式・合格ライ...

Snowflake

SnowPro Platform Associate完全解説|入門試験の攻略

SnowPro Associate: Platform Certification(SOL-C01)を徹底解説。最も簡単...

Snowflakeの記事一覧 (102件)
© 2026 NicheeLab All rights reserved.