클래식 API와 함께 데이터 분류 사용하기¶
이 항목에서는 Snowflake의 클래식 API인 EXTRACT_SEMANTIC_CATEGORIES 및 ASSOCIATE_SEMANTIC_CATEGORY_TAGS 를 사용하여 데이터를 분류하는 예를 제시합니다. 이러한 API는 데이터 분류 업데이트에 맞춰 더 이상 업데이트되지 않습니다.
이러한 API를 계속 사용할 수 있습니다. 그러나 데이터 분류 사용하기 에 표시된 접근 방식을 사용하려면 워크플로를 업데이트해야 합니다.
이 항목의 내용:
개요¶
데이터 분류에 대한 다음 예제에서는 범위를 기준으로 다양한 사용 사례를 다룹니다.
새로운 분류 사용자라면 단일 테이블 분류로 시작한 다음 다른 두 예제로 진행하십시오.
공통 테이블 및 역할¶
이 항목에 나오는 예제에서는 아래에 표시된 테이블과 사용자 지정 역할을 사용합니다.
테이블: 직원에 대한 데이터를 포함한
my_db.my_schema.hr_data
.역할:
data_engineer
: 테이블을 분류합니다.policy_admin
: 마스킹 정책으로 개인 정보를 보호합니다.analyst
: 액세스를 제한하고 싶은 사용자 지정 역할의 예로 사용됩니다. 예제에서는 이 역할이 존재한다고 가정합니다.-
GOVERNANCE_ADMIN: 분류 시스템 태그를 할당합니다.
GOVERNANCE_VIEWER: 태그 및 마스킹 정책과 관련된 Account Usage 뷰를 쿼리합니다.
테이블 만들기:
CREATE OR REPLACE TABLE hr_data ( age INTEGER, email_address VARCHAR, fname VARCHAR, lname VARCHAR );
테이블을 로딩합니다(세부 정보는 표시되지 않음).
사용자 지정 역할을 만들고 그와 같은 역할에 필요한 권한을 부여합니다.
data_engineer
역할이 분류 프로세스를 실행하려면 테이블에 대한 액세스 권한이 필요합니다. 역할을 데이터베이스 역할로 전환할 수 없으므로 이 예제에서는data_engineer
역할에 GOVERNANCE_ADMIN 데이터베이스 역할을 부여합니다.use role accountadmin; create 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 database role snowflake.governance_admin to role data_engineer;
policy_admin
사용자 지정 역할은 PII 데이터를 포함하는 모든 열에 마스킹 정책을 할당해야 합니다.use role accountadmin; create role policy_admin; grant apply masking policy on account to role policy_admin; grant database role snowflake.governance_viewer to role policy_admin;
단일 테이블 분류하기¶
단일 테이블 예제에서는 3단계 분류 프로세스(분석, 검토, 적용)를 확장하여 결과를 적용해 analyst
사용자 지정 역할에서 테이블 액세스 권한을 취소합니다.
1단계: 테이블 열 분류¶
이 단계에서 data_engineer
는 분류 프로세스를 실행하고 policy_admin
은 마스킹 정책 으로 열 데이터를 보호합니다.
분석:
data_engineer
사용자 지정 역할을 사용하여 EXTRACT_SEMANTIC_CATEGORIES 함수를 호출해my_db.my_schema.hr_data
라는 테이블의 열을 분류합니다.USE ROLE data_engineer; SELECT EXTRACT_SEMANTIC_CATEGORIES('my_db.my_schema.hr_data');
검토: 데이터 엔지니어가 결과가 타당한지 검토합니다.
적용: 데이터 엔지니어가 분류 시스템 태그를 열에 할당합니다.
데이터 엔지니어에게는 자동 할당 또는 수동 할당의 두 가지 옵션이 있습니다.
시스템 태그를 자동으로 할당하려면 ASSOCIATE_SEMANTIC_CATEGORY_TAGS 저장 프로시저를 호출하십시오. 참고:
테이블의 정규화된 이름과 첫 번째 단계의 함수는 저장 프로시저의 인자입니다.
저장 프로시저는 EXTRACT_SEMANTIC_CATEGORIES 함수를 다시 실행합니다. 첫 번째 단계의 결과를 보존하려면 저장 프로시저를 호출하기 전에 결과를 테이블에 저장하십시오.
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.
그렇지 않고 저장 프로시저가 실행되지 않을 때나 필요에 따라 각 열에 분류 시스템 태그를 수동으로 할당하기로 결정한 경우 ALTER TABLE … ALTER 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단계: 테이블 열 보호¶
이 단계에서는 my_db.my_schema.hr_data
테이블의 여러 열에 PRIVACY_CATEGORY = 'IDENTIFIER'
태그가 할당되어 있고 마스킹 정책으로 이러한 열을 보호할 필요가 있다고 가정합니다.
이러한 열을 보호하는 방법:
policy_admin
역할을 사용하여 IDENTIFIER 개인정보 보호 태그가 적용된 열을 찾습니다.USE ROLE policy_admin; SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.TAG_REFERENCES WHERE TAG_NAME = 'PRIVACY_CATEGORY' AND TAG_VALUE = 'IDENTIFIER';
TAG_REFERENCES 뷰의 지연 시간은 최대 120분일 수 있습니다. 결과가 더 빨리 필요하고 분류 태그를 쿼리하는 열의 이름을 아는 경우, TAG_REFERENCES 또는 TAG_REFERENCES_ALL_COLUMNS 테이블 함수를 대신 사용할 수 있습니다.
policy_admin
역할을 사용하여 적절한 열에 마스킹 정책을 적용합니다. 예를 들어 다음 문은identifier_mask
마스킹 정책을fname
열에 적용합니다.ALTER TABLE my_db.my_schema.hr_data MODIFY COLUMN fname SET MASKING POLICY governance.policies.identifier_mask;
스키마의 모든 테이블 분류하기¶
이 예에서는 두 개의 사용자 정의 저장 프로시저를 사용하여 스키마의 모든 테이블을 분류하는 방법을 보여줍니다.
classify_schema
: 스키마의 모든 테이블을 나열하고, 분류 결과를 저장할 테이블을 만든 다음, 각 테이블에서 분류 태그를 추출하여 결과 테이블에 저장합니다.associate_tag_batch
:classify_schema
저장 프로시저의 결과를 사용하여 분류 시스템 태그를 스키마의 모든 테이블 열에 자동으로 할당하고 각 테이블에 할당된 태그 수를 반환합니다.
중요
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 $$ // 1 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()}; $$;
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; $$;
분류하려는 스키마의 이름과 각 테이블에 대한 EXTRACT_SEMANTIC_CATEGORY의 결과를 가진 임시 테이블의 이름을 인자로 사용하여
classify_schema
저장 프로시저를 호출합니다.call classify_schema('my_db.my_schema','my_temporary_classification_table');
임시 테이블의 결과를 검토하고 필요에 따라 수정합니다.
결과에 만족하면 다음과 같이
associate_tag_batch
저장 프로시저를 호출하여 분류 시스템 태그를 테이블 열에 할당합니다.call associate_tag_batch('my_temporary_classification_table');
데이터베이스의 모든 테이블 분류하기¶
이 예에서는 두 개의 저장 프로시저를 사용하여 데이터베이스의 모든 테이블을 분류하는 방법을 보여줍니다.
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, }; $$;
분류하려는 데이터베이스의 이름과 데이터베이스의 각 스키마에 결과를 저장할 임시 테이블의 이름으로
classify_database
저장 프로시저를 호출합니다.call classify_database('my_db','my_temporary_classification_table');
각 스키마로 이동하여 임시 테이블을 검토하고 필요한 경우 수정합니다.
결과에 만족하면 다음과 같이 각 스키마에 대해
associate_tag_batch
저장 프로시저를 한 번 호출하여 해당 스키마의 테이블에 태그를 적용합니다. 예를 들어 데이터베이스에 세 개의 스키마가 포함된 경우 저장 프로시저를 세 번 호출합니다.call associate_tag_batch('my_temporary_classification_table');