Skip to main content

1. 왜 시스템 테이블이 필요한가

관찰가능성 (Observability) 부재 문제

데이터 플랫폼을 운영하다 보면 다음과 같은 질문이 반복적으로 생깁니다.
  • “이번 달 클라우드 비용이 갑자기 왜 늘었지?”
  • “누가 프로덕션 테이블을 실수로 삭제했을까?”
  • “이 파이프라인 Job이 점점 느려지는 것 같은데, 언제부터였지?”
  • “우리 팀에서 실제로 사용하지 않는 클러스터가 얼마나 되지?”
전통적인 데이터 플랫폼에서는 이런 질문에 답하려면 CloudWatch, CloudTrail, 별도 APM 도구, 혹은 수동 로그 분석이 필요했습니다. 도구가 분산되어 있고, 데이터 형식도 제각각이며, SQL로 바로 분석할 수 없다는 문제가 있었습니다. 시스템 테이블(System Tables) 은 이 문제를 해결합니다. Databricks 플랫폼이 스스로 생산하는 운영 데이터를 system 카탈로그 아래의 표준 테이블로 제공하여, 익숙한 SQL 한 줄로 플랫폼 전반을 관찰할 수 있게 합니다.

시스템 테이블로 해결하는 주요 과제

과제기존 방식시스템 테이블 방식
클라우드 비용 관리AWS Cost Explorer + 수동 태깅system.billing.usage SQL 분석
보안 감사 (Security Audit)CloudTrail JSON 파싱system.access.audit 직접 조회
사용량 분석워크스페이스별 개별 확인계정 전체 통합 뷰
성능 / SLA 모니터링Job 로그 수동 확인system.lakeflow.job_run_timeline 집계
데이터 리니지 (Lineage)별도 메타데이터 도구system.lineage.table_lineage

2. 시스템 테이블 개요

system 카탈로그 구조

system (카탈로그)
├── access           ← 보안 감사 로그
│   ├── audit
│   └── table_lineage (access 스키마의 lineage 뷰)
├── billing          ← 비용 / DBU 사용량
│   ├── usage
│   └── list_prices
├── compute          ← 클러스터 / 웨어하우스
│   ├── clusters
│   └── warehouse_events
├── lakeflow         ← Job / 워크플로우 실행
│   ├── jobs
│   ├── job_tasks
│   └── job_run_timeline
├── lineage          ← 데이터 리니지
│   ├── table_lineage
│   └── column_lineage
└── storage          ← 스토리지 최적화
    └── predictive_optimization_operations_history

활성화 방법

시스템 테이블은 Unity Catalog 가 활성화된 계정에서만 사용할 수 있습니다. 대부분의 테이블은 자동으로 활성화되지만, 일부 스키마는 Account Admin이 명시적으로 활성화해야 합니다. Account Console → Settings → System tables 메뉴에서 각 스키마를 활성화합니다. 또는 REST API로도 가능합니다.
# REST API로 특정 스키마 활성화 (예: billing)
curl -X PUT "https://accounts.azuredatabricks.net/api/2.0/accounts/{account_id}/metastores/{metastore_id}/systemschemas/billing" \
  -H "Authorization: Bearer <token>"
참고: System tables - Databricks Documentation

데이터 보존 기간 (Data Retention)

스키마보존 기간
system.billing.usage365일
system.access.audit365일
system.compute.clusters365일
system.lakeflow.*365일
system.lineage.*90일
system.storage.*365일
주의: 보존 기간은 Databricks 정책에 따라 변경될 수 있습니다. 장기 보관이 필요하다면 별도 테이블로 복사하는 파이프라인 구축을 권장합니다.

3. 주요 시스템 테이블 상세

3-1. system.billing.usage — 비용 분석

system.billing.usage 는 Databricks의 모든 워크로드에서 소비한 DBU (Databricks Unit) 사용량을 행 단위로 기록합니다. 클러스터, SQL Warehouse, Jobs, Serverless, DLT 파이프라인 등 모든 제품의 사용량이 포함됩니다. 주요 컬럼
컬럼설명
usage_date사용 날짜
sku_nameSKU 이름 (예: STANDARD_ALL_PURPOSE_COMPUTE)
billing_origin_product제품 유형 (JOBS, SQL, ALL_PURPOSE, DLT 등)
usage_quantity소비한 DBU 수량
usage_metadata.cluster_id관련 클러스터 ID
usage_metadata.warehouse_id관련 웨어하우스 ID
usage_metadata.job_id관련 Job ID
identity_metadata.run_as실행한 사용자 이메일
custom_tags워크로드에 붙은 커스텀 태그
system.billing.list_prices 를 조인하면 DBU를 실제 USD 비용으로 변환할 수 있습니다.
-- 지난 30일간 워크로드 유형별 DBU 사용량 및 비용 추정
SELECT
    billing_origin_product,
    sku_name,
    SUM(u.usage_quantity)                              AS total_dbus,
    ROUND(SUM(u.usage_quantity * p.pricing.default), 2) AS estimated_cost_usd
FROM system.billing.usage u
LEFT JOIN system.billing.list_prices p
    ON u.sku_name = p.sku_name
    AND u.usage_date BETWEEN p.price_start_time::DATE AND COALESCE(p.price_end_time::DATE, CURRENT_DATE())
WHERE u.usage_date >= CURRENT_DATE() - INTERVAL 30 DAYS
GROUP BY 1, 2
ORDER BY estimated_cost_usd DESC;

-- 일별 비용 추이 (급증 감지용)
SELECT
    usage_date,
    billing_origin_product,
    SUM(usage_quantity) AS daily_dbus
FROM system.billing.usage
WHERE usage_date >= CURRENT_DATE() - INTERVAL 90 DAYS
GROUP BY 1, 2
ORDER BY usage_date, billing_origin_product;

-- 사용자별 DBU 소비 TOP 10
SELECT
    identity_metadata.run_as   AS user_email,
    billing_origin_product     AS product,
    SUM(usage_quantity)        AS total_dbus
FROM system.billing.usage
WHERE usage_date >= CURRENT_DATE() - INTERVAL 30 DAYS
GROUP BY 1, 2
ORDER BY total_dbus DESC
LIMIT 10;

3-2. system.access.audit — 감사 로그

system.access.audit 는 Databricks 플랫폼에서 발생하는 모든 사용자 활동 을 기록합니다. 테이블 조회, 클러스터 생성, 권한 변경, 토큰 발급 등 모든 API 호출이 포함됩니다. 보안 감사(Security Audit), GDPR/규정 준수, 내부 보안 정책 이행 증빙에 핵심적으로 사용됩니다. 주요 컬럼
컬럼설명
event_time이벤트 발생 시각 (UTC)
event_date이벤트 날짜
workspace_id워크스페이스 ID
action_name수행된 액션 (예: getTable, createCluster, deletePermissions)
user_identity.email행위자 이메일
source_ip_address요청 발생 IP
request_params요청 파라미터 (JSON)
response.status_code응답 상태 코드
service_name서비스 이름 (예: clusters, unityCatalog)
-- 최근 7일간 누가 어떤 테이블에 접근했는지 확인
SELECT
    event_date,
    user_identity.email     AS user_email,
    action_name,
    request_params.full_name_arg AS table_name,
    source_ip_address
FROM system.access.audit
WHERE action_name IN ('getTable', 'commandSubmit')
    AND event_date >= CURRENT_DATE() - INTERVAL 7 DAYS
ORDER BY event_date DESC
LIMIT 100;

-- 비정상 접근 패턴 감지: 야간 시간대(22시~06시) 활동
SELECT
    user_identity.email,
    COUNT(*)                    AS late_night_actions,
    COLLECT_SET(action_name)    AS action_types
FROM system.access.audit
WHERE HOUR(event_time) NOT BETWEEN 6 AND 22
    AND event_date >= CURRENT_DATE() - INTERVAL 30 DAYS
GROUP BY user_identity.email
HAVING COUNT(*) > 10
ORDER BY late_night_actions DESC;

-- 권한 변경 이력 (중요 보안 이벤트)
SELECT
    event_time,
    user_identity.email     AS actor,
    action_name,
    request_params
FROM system.access.audit
WHERE action_name IN (
    'updatePermissions', 'grantPrivileges', 'revokePrivileges',
    'createCredential', 'deleteCredential'
)
    AND event_date >= CURRENT_DATE() - INTERVAL 30 DAYS
ORDER BY event_time DESC;

3-3. system.compute.clusters — 클러스터 사용 현황

system.compute.clusters 는 계정 내 모든 클러스터의 설정, 상태, 이벤트 이력 을 제공합니다. 비용 누수(자동 종료 미설정, 과도한 노드 수)를 발견하고, 클러스터 사용 패턴을 최적화하는 데 활용합니다. 주요 컬럼
컬럼설명
cluster_id클러스터 고유 ID
cluster_name클러스터 이름
cluster_source생성 주체 (UI, JOB, API)
driver_node_type드라이버 노드 타입
node_type_id워커 노드 타입
autoscale오토스케일 설정 (min/max 워커 수)
autotermination_minutes자동 종료까지의 유휴 시간(분)
state현재 상태 (RUNNING, TERMINATED, PENDING)
state_start_time상태 시작 시각
owned_by클러스터 소유자
custom_tags커스텀 태그
-- 자동 종료 설정이 없거나 너무 긴 클러스터 (비용 누수 리스크)
SELECT
    cluster_id,
    cluster_name,
    owned_by,
    autotermination_minutes,
    state,
    TIMESTAMPDIFF(HOUR, state_start_time, CURRENT_TIMESTAMP()) AS running_hours
FROM system.compute.clusters
WHERE state = 'RUNNING'
    AND (autotermination_minutes IS NULL OR autotermination_minutes > 120)
ORDER BY running_hours DESC;

-- 클러스터 유형별 분포 파악
SELECT
    cluster_source,
    node_type_id,
    COUNT(DISTINCT cluster_id)  AS cluster_count,
    AVG(autotermination_minutes) AS avg_autotermination_min
FROM system.compute.clusters
WHERE state_start_time >= CURRENT_DATE() - INTERVAL 30 DAYS
GROUP BY 1, 2
ORDER BY cluster_count DESC;