分類の使用

このトピックでは、分類ワークフローの一般的な概要と、分類を使用してタグを生成し、データベーステーブル、ビュー、および列に適用する詳細な例を示します。

このトピックの内容:

分類ワークフロー

テーブルまたはビューでのデータの分類には、次のタスクが含まれます。

  1. 分類とタグ付けの権限を委任する。

    アカウント管理者(つまり、 ACCOUNTADMIN ロールを持つユーザー)は、タグを適用するために必要な権限を1つ以上のカスタムロール(例 data_engineer)に付与します。

  2. テーブル/ビューの列を分析する。

    データエンジニア(つまり、 data_engineer ロールを持つユーザー)は、 EXTRACT_SEMANTIC_CATEGORIES 関数を使用して、以前の分類結果がないテーブル/ビューを分析します。Snowflakeは、テーブル/ビューでサポートされている列のセマンティックカテゴリとプライバシーカテゴリを生成します。

  3. タグを適用して、テーブル/ビューの列を分類する。

    データエンジニアは、セマンティックカテゴリとプライバシーカテゴリに従って列に注釈を付けます。

    ちなみに

    ASSOCIATE_SEMANTIC_CATEGORY_TAGS を呼び出して EXTRACT_SEMANTIC_CATEGORIES からの出力を渡すことにより、ステップ2と3をまとめることができます。

    EXTRACT_SEMANTIC_CATEGORIES の出力をフラット化 して、データベーステーブルに保存し、適用や再利用の前に変更しやすくすることもできます。

  4. 更新されたデータと新しいデータの分類タグをモニターおよび維持します。

    実行されるタスクは、テーブル/ビューにデータまたは列が追加/変更されているかどうかによって異なります。

    • データが追加または削除された場合、データエンジニアはテーブル/ビューで EXTRACT_SEMANTIC_CATEGORIES 関数を再度実行します。Snowflakeは、新しいセマンティックおよびプライバシーカテゴリの結果を生成します。

      次に、データエンジニアは新しい結果を既存の結果と比較し、それに応じてタグを手動で変更するか、 ASSOCIATE_SEMANTIC_CATEGORY_TAGS ストアドプロシージャを使用して新しい結果を適用し、現在のタグを上書きします。

    • 新しい列が追加されると、データエンジニアは、テーブル/ビューで EXTRACT_SEMANTIC_CATEGORIES 関数を再度実行します。

      次に、データエンジニアは、セマンティックカテゴリとプライバシーカテゴリに従って新しい列に手動で注釈を付けるか、 ASSOCIATE_SEMANTIC_CATEGORY_TAGS ストアドプロシージャを使用します。

注釈

前述のように、ユーザーは、 EXTRACT_SEMANTIC_CATEGORIES 関数によって返される結果を使用しない(または選択的にのみ使用する)ことを選択できます。

さらに、ユーザーは、Snowflakeが提供する分類カテゴリを手動で適用するか、独自の分類 タグ のセットを定義して適用するかを選択できます。

タグを手動で適用する例については、 分類タグをテーブル/ビューに手動で適用する をご参照ください。

分類タグの使用

これらの例で使用するテーブルとロールを作成する

このトピックのほとんどの例では、以下に示すテーブルとカスタムロールを使用しています。

  • テーブル

    • hr_data には、従業員に関するデータが含まれています。

  • ロール

    • data_engineer は、分類タグの生成と適用ができます。

    • policy_admin には、個人情報がマスクされていることを確認する責任があります。

    • analyst は、アクセスを制限する必要がある可能性のあるロールの例です。(以下のサンプルコードは、このロールがすでに存在することを前提としています。)

テーブルを作成します。

CREATE TABLE hr_data (
    age INTEGER,
    email_address VARCHAR,
    fname VARCHAR,
    lname VARCHAR
    );

テーブルをロードします(詳細表示なし)。

カスタムロールを作成し、それらのロールに必要な権限を付与します。

USE ROLE ACCOUNTADMIN;

CREATE ROLE data_engineer;

GRANT IMPORTED PRIVILEGES ON DATABASE snowflake TO ROLE data_engineer;

GRANT USAGE ON DATABASE my_db TO ROLE data_engineer;

GRANT USAGE ON SCHEMA my_db.my_schema TO ROLE data_engineer;

GRANT SELECT, UPDATE ON TABLE my_db.my_schema.hr_data TO ROLE data_engineer;

GRANT APPLY TAG ON ACCOUNT TO ROLE data_engineer;

CREATE ROLE policy_admin;

分類タグを使用してマスキングポリシーを適用する

この例は、分類を使用してテーブルの列で個人を特定できるデータを検索し、列にタグを付けてから、タグを使用して マスキングポリシー をデータに適用する方法を示しています。

この例では、

  • data_engineer カスタムロールは、次のタグ付け関連のタスクを実行します。

  • policy_admin カスタムロールは、次のマスキング関連のタスクを実行します。

    • TAG_REFERENCES ビューを使用して、 IDENTIFIER プライバシータグが適用されている列を検索します。

    • identifier_mask マスキングポリシーを fname 列に適用します。

注釈

TAG_REFERENCES ビューの待機時間は最大120分です。より早く結果が必要で、分類タグをクエリする列の名前がわかっている場合は、代わりに TAG_REFERENCES または TAG_REFERENCES_ALL_COLUMNS テーブル関数を使用できます。

例については、 分類データの表示と追跡 (このトピック内)をご参照ください。

data_engineer ロールを使用して、分類タグを生成します。

USE ROLE data_engineer;

SELECT EXTRACT_SEMANTIC_CATEGORIES('my_db.my_schema.hr_data');

タグが受け入れられる場合、 data_engineer ロールはそれらをテーブルに適用できます。

CALL ASSOCIATE_SEMANTIC_CATEGORY_TAGS('my_db.my_schema.hr_data',
                                      EXTRACT_SEMANTIC_CATEGORIES('my_db.my_schema.hr_data'));

ストアドプロシージャが正常に実行されると、次のようなメッセージが返されます。 Applied tag semantic_category to <n> columns. Applied tag privacy_category to <n> columns.

policy_admin ロールを使用して、 IDENTIFIER プライバシータグが適用されている列を検索します。

USE ROLE policy_admin;

SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.TAG_REFERENCES
    WHERE TAG_NAME = 'PRIVACY_CATEGORY'
    AND TAG_VALUE = 'IDENTIFIER';

policy_admin ロールを使用して、適切な列にマスキングポリシーを適用します。たとえば、次のステートメントは identifier_mask ポリシーを fname 列に適用します。

ALTER TABLE my_db.my_schema.hr_data MODIFY COLUMN fname SET MASKING POLICY identifier_mask;

分類タグを使用してアクセスを取り消す

この例は、 分類タグを使用してマスキングポリシーを適用する (このトピック内)場合の例を継続していますが、 SECURITYADMIN システムロールを使用し、分類タグに基づいてアクセス権限を管理します。

この例では、

  • SECURITYADMIN ロールは、 TAG_REFERENCES ビューを使用して、 IDENTIFIER プライバシータグを持つすべての列を検索します。

  • SECURITYADMIN ロールは、 analyst カスタムロールからテーブル(列を含む)への SELECT アクセスを取り消します。

注釈

これらのタスクを実行するために SECURITYADMIN システムロールを使用する必要はありません。必要な権限が割り当てられている任意のカスタムロールを使用できます。

USE ROLE SECURITYADMIN;

SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.TAG_REFERENCES
    WHERE TAG_NAME = 'PRIVACY_CATEGORY'
    AND TAG_VALUE= 'IDENTIFIER';

REVOKE SELECT ON TABLE my_db.my_schema.hr_data FROM ROLE analyst;

分類タグをテーブル/ビューに手動で適用する

この例は、 分類タグを使用してマスキングポリシーを適用する (このトピック内)場合の例を継続していますが、生成された分類カテゴリがテーブルに適用されていないことを前提としています。

この例では、

  • テーブルの分類カテゴリを生成した後、 data_engineer ロールは結果を確認し、カテゴリを適用するためにストアドプロシージャを使用しないことを決定します。

  • 代わりに、 data_engineer ロールは ALTER TABLE ... MODIFY COLUMN コマンドを使用して、セマンティックカテゴリおよびプライバシーカテゴリのタグをテーブルの fname 列に手動で適用します。

USE ROLE data_engineer;

ALTER TABLE my_db.my_schema.hr_data MODIFY COLUMN fname SET TAG SNOWFLAKE.CORE.SEMANTIC_CATEGORY='NAME';

ALTER TABLE my_db.my_schema.hr_data MODIFY COLUMN fname SET TAG SNOWFLAKE.CORE.PRIVACY_CATEGORY='IDENTIFIER';

スキーマまたはデータベース内にあるすべてのテーブルを分類する

ストアドプロシージャを使用して、スキーマ内にあるすべてのテーブルを分類する

この例は、作成した2つのストアドプロシージャを使用して、スキーマ内にあるすべてのテーブルを分類する方法を示しています。

  • classify_schema: スキーマ内のすべてのテーブルをリストし、分類結果を格納するテーブルを作成してから、分類タグを各テーブルから抽出して結果テーブルに格納します。

  • associate_tag_batch: 結果テーブルのタグをスキーマのすべてのテーブルに関連付けます。

重要

classify_schema という名前のストアドプロシージャは、結果を格納する仮テーブルを作成します。仮テーブルは、このストアドプロシージャを呼び出すユーザーのユーザーセッションの期間中、存在します。ユーザーセッションが期限切れになると、Snowflakeは仮テーブルをドロップするため、ユーザーはストアドプロシージャを再度呼び出して、仮テーブルを再作成する必要があります。

仮テーブルを保持する必要がある場合は、 sqlText コマンドから temp キーワードを削除してテーブルを作成します。

詳細については、 CREATE TABLE コマンドにある TEMP[ORARY] オプションをご参照ください。

最初のプロシージャ(classify_schema)を作成します。

create or replace procedure classify_schema(schema_name string, result_table string)
returns object language JavaScript
as $$
// get list of tables in schema
const table_names = snowflake.execute({
  sqlText: `show terse tables in schema identifier(?)`,
  binds: [SCHEMA_NAME],
});

// helper function for quoted table names
function quote(name) {
  return '"'+ name.replace(/"/g,'""') + '"';
}

// create table to store results in. if it already exists, we will add to it rather than overwrite
snowflake.execute({
    sqlText: `create temp table if not exists identifier(?) (table_name string, result variant)`,
    binds: [RESULT_TABLE],
})
// loop through tables
while (table_names.next()) {
  let name = table_names.getColumnValue('name');
  // add schema to table name
  name = SCHEMA_NAME + "." + quote(name);
  // insert qualified table name and result into result table
  const results = snowflake.execute({
    sqlText: `insert into identifier(?) select ?, extract_semantic_categories(?)`,
    binds: [RESULT_TABLE, name, name],
  });
}
// return the number of tables classified
return {tables_classified: table_names.getRowCount()};
$$;

2番目のプロシージャ(associate_tag_batch)を作成します。

create or replace procedure associate_tag_batch(result_table string)
returns Object language JavaScript
as $$
// get table names and classification results to loop through
const tags_to_apply = snowflake.execute({
  sqlText: `select table_name, result from identifier(?)`,
  binds: [RESULT_TABLE],
});

const out = {};
while (tags_to_apply.next()) {
  // get table name
  const name = tags_to_apply.getColumnValue('TABLE_NAME');
  // get classification result
  const classification_results = tags_to_apply.getColumnValue('RESULT');
  // call associate semantic category tags with table name and classification result
  const results = snowflake.execute({
    sqlText: `call associate_semantic_category_tags(?, parse_json(?))`,
    binds: [name, JSON.stringify(classification_results)],
  });
  results.next();
  out[name] = results.getColumnValue(1).split('\n');
}
// return number of tags applied per table
return out;
$$;

そして、次のステップを実行します。

  1. 分類するスキーマの名前と、各テーブルの EXTRACT_SEMANTIC_CATEGORY の結果を保持する仮テーブルの名前を使用して、 classify_schema ストアドプロシージャを呼び出します。

    call classify_schema('my_db.my_schema','my_temporary_classification_table');
    
  2. 仮テーブルの結果を確認し、必要に応じて変更します。

  3. 結果が十分な場合は、 associate_tag_batch ストアドプロシージャを呼び出してタグを適用します。

    call associate_tag_batch('my_temporary_classification_table');
    

ストアドプロシージャを使用して、データベース内にあるすべてのテーブルを分類する

この例は、2つのストアドプロシージャを使用して、データベース内にあるすべてのテーブルを分類する方法を示しています。

  • classify_database (この例で新規)。

  • associate_tag_batch (前のセクションの例で作成)。

classify_database ストアドプロシージャを作成します。

create or replace procedure classify_database(database_name string, result_table string)
returns Object language JavaScript
as $$
// get list of schemas in database
const schema_names = snowflake.execute({
  sqlText: `show terse schemas in database identifier(?)`,
  binds: [DATABASE_NAME],
});

// helper function for quoted schema names
function quote(name) {
  return '"'+ name.replace(/"/g,'""') + '"';
}

// counter for tables. will use result from classify_schema to increment
let table_count = 0
while (schema_names.next()) {
  let name = schema_names.getColumnValue('name');
  // skip the information schema
  if (name == "INFORMATION_SCHEMA") {
    continue;
  }
  // add database name to schema
  name = DATABASE_NAME + "." + quote(name);
  // call classify_schema on each schema. This will loop over tables in schema
  const results = snowflake.execute({
    sqlText: `call classify_schema(?, ?)`,
    binds: [name, RESULT_TABLE],
  });
  results.next();
  // increment total number of tables by the number of tables in the schema
  table_count += results.getColumnValue(1).tables_classified ;
}

return {
    tables_classified: table_count,
    // subtract one from number of schemas because we skip the information schema
    schemas_classified: schema_names.getRowCount() - 1,
};
$$;

そして、次のステップを実行します。

  1. 分類するデータベースの名前と仮テーブルの名前を使用して classify_database ストアドプロシージャを呼び出し、データベースの各スキーマに結果を保存します。

    call classify_database('my_db','my_temporary_classification_table');
    
  2. 各スキーマに移動して、仮テーブルを確認し、必要に応じて修正します。

  3. 結果が十分な場合は、 スキーマに対して associate_tag_batch ストアドプロシージャを1回呼び出し、そのスキーマのテーブルにタグを適用します。

    call associate_tag_batch('my_temporary_classification_table');
    

分類出力の半構造化形式から構造化形式への変換

セマンティック分類関数 EXTRACT_SEMANTIC_CATEGORIES は、半構造化形式である JSON 形式の VARCHAR を返します。出力を構造化(表形式)形式に変換する場合は、以下に示すように、 FLATTEN テーブル関数を使用します。

これらの例では、 これらの例で使用するテーブルとロールを作成する (このトピック内)で作成したテーブルを使用します。

以下に、フラット化しない場合の EXTRACT_SEMANTIC_CATEGORIES 関数の出力を示します。

SELECT EXTRACT_SEMANTIC_CATEGORIES('hr_data');
+---------------------------------------------+
| EXTRACT_SEMANTIC_CATEGORIES('HR_DATA')      |
|---------------------------------------------|
| {                                           |
|   "AGE": {                                  |
|     "extra_info": {                         |
|       "alternates": [],                     |
|       "probability": "1.00"                 |
|     },                                      |
|     "privacy_category": "QUASI_IDENTIFIER", |
|     "semantic_category": "AGE"              |
|   },                                        |
|   "EMAIL_ADDRESS": {                        |
|     "extra_info": {                         |
|       "alternates": [],                     |
|       "probability": "1.00"                 |
|     },                                      |
|     "privacy_category": "IDENTIFIER",       |
|     "semantic_category": "EMAIL"            |
|   },                                        |
|   "FNAME": {                                |
|     "extra_info": {                         |
|       "alternates": [],                     |
|       "probability": "1.00"                 |
|     },                                      |
|     "privacy_category": "IDENTIFIER",       |
|     "semantic_category": "NAME"             |
|   },                                        |
|   "LNAME": {                                |
|     "extra_info": {                         |
|       "alternates": [],                     |
|       "probability": "0.97"                 |
|     },                                      |
|     "privacy_category": "IDENTIFIER",       |
|     "semantic_category": "NAME"             |
|   }                                         |
| }                                           |
+---------------------------------------------+

以下に、フラット化した場合の EXTRACT_SEMANTIC_CATEGORIES 関数の出力を示します。

SELECT
    f.key::varchar as column_name,
    f.value:"privacy_category"::varchar as privacy_category,  
    f.value:"semantic_category"::varchar as semantic_category,
    f.value:"extra_info":"probability"::number(10,2) as probability,
    f.value:"extra_info":"alternates"::variant as alternates
  FROM
  TABLE(FLATTEN(EXTRACT_SEMANTIC_CATEGORIES('hr_data')::VARIANT)) AS f;
+---------------+------------------+-------------------+-------------+------------+
| COLUMN_NAME   | PRIVACY_CATEGORY | SEMANTIC_CATEGORY | PROBABILITY | ALTERNATES |
|---------------+------------------+-------------------+-------------+------------|
| AGE           | QUASI_IDENTIFIER | AGE               |        1.00 | []         |
| EMAIL_ADDRESS | IDENTIFIER       | EMAIL             |        1.00 | []         |
| FNAME         | IDENTIFIER       | NAME              |        1.00 | []         |
| LNAME         | IDENTIFIER       | NAME              |        0.97 | []         |
+---------------+------------------+-------------------+-------------+------------+

PROBABILITY フィールドなど、一部のフィールドの値は、データの特性とサンプルサイズによって異なることに注意してください。

分類データの表示と追跡

Snowflakeは、分類によって生成されたセマンティックタグとプライバシータグを表示するために使用できる、Account UsageとInformation Schemaのビューと関数を提供します。

  • 列に関連付けられているすべての分類タグのリストを取得するには、 TAG_REFERENCES ビュー(Account Usage内)をクエリします。ただし、ビューの待ち時間は最大120分になる可能性があることに注意してください。

    例:

    SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.TAG_REFERENCES
        WHERE TAG_NAME = 'PRIVACY_CATEGORY'
        ORDER BY OBJECT_DATABASE, OBJECT_SCHEMA, OBJECT_NAME, COLUMN_NAME;
    
  • 特定のテーブル/ビューの名前がわかっている場合は、待機時間のない TAG_REFERENCES_ALL_COLUMNS テーブル関数(Information Schema内)を使用できます。

    この関数は、指定されたテーブル/ビューの列にあるすべての分類タグのリストを返します。

  • 分類タグを表示する特定のテーブル/ビュー列の名前がわかっている場合は、 TAG_REFERENCES テーブル関数(Information Schema内)を使用できます。これにも待機時間はありません。

    例:

    SELECT * FROM
        TABLE(my_db.information_schema.tag_references('my_db.my_schema.hr_data.fname', 'COLUMN'));
    
最上部に戻る