Snowflake MigrationClickHouse Workshops

ClickHouse의 Superset

ClickHouse를 대상으로 대시보드 재구축: uniqHLL12, quantileTDigest, 샘플링, 윈도 함수, dictGet을 사용하는 7개 데이터셋과 4개 대시보드에 걸친 18개 차트.

이 가이드는 Superset에서 모든 ClickHouse 데이터셋, 차트, 대시보드를 수동으로 설정하는 전 과정을 안내합니다. 각 시각화가 무엇을 하고 어떻게 만들어지는지 이해하려면 이 과정을 따라가세요.

건너뛰고 싶다면? 가져오기 스크립트를 실행하면 모든 것이 자동으로 생성됩니다:

source .env && source .clickhouse_state
bash superset/add_clickhouse_connection.sh

이 스크립트는 연결을 생성하고, 7개 데이터셋, 18개 차트, 4개 대시보드를 한 번에 가져옵니다. 이 가이드는 참조용으로, 또는 개별 요소를 다시 만들 때 사용하세요.

중요 — superset/dashboards/dashboard_export_*.zip 안의 플레이스홀더 자격 증명.

커밋된 대시보드 ZIP은 databases/*.yaml이 플레이스홀더로 마스킹되어 있습니다:

sqlalchemy_uri: clickhousedb://default:XXXXXXXXXX@your-instance.clickhouse.cloud:8443/analytics?secure=true
  • 자동 가져오기(add_clickhouse_connection.sh) — 그대로 작동합니다. 스크립트는 가져오기 엔드포인트로 전송하기 전에 .env의 ${CLICKHOUSE_HOST} / ${CLICKHOUSE_USER} / ${CLICKHOUSE_PASSWORD}를 사용해 ZIP 내부의 sqlalchemy_uri를 다시 쓰므로, 플레이스홀더 호스트는 Superset에 절대 도달하지 않습니다.
  • Superset UI를 통한 수동 가져오기 — 가져온 데이터베이스는 your-instance.clickhouse.cloud로 생성되어 연결되지 않습니다. 가져온 후 Settings → Database Connections → Edit로 이동해 해당 항목의 sqlalchemy_uri를 실제 ClickHouse Cloud URI로 교체하세요(예: clickhousedb://default:<PASSWORD>@<your-host>.clickhouse.cloud:8443/analytics?secure=true).
  • 직접 만든 대시보드를 다시 내보내기 — Superset은 내보내기에 여러분의 실제 ClickHouse 호스트를 그대로 넣습니다. 커밋하기 전에 호스트를 your-instance.clickhouse.cloud로 되돌려 마스킹해서 서비스 식별자가 git 히스토리로 유출되지 않게 하세요.

사전 조건: analytics 계층이 채워져 있고(7.3단계에서 dbt run 완료) 딕셔너리가 존재해야 합니다(7.4단계에서 scripts/04_create_dictionary.sql 완료).


0단계 — ClickHouse 연결 등록

  1. http://localhost:8088의 Superset에 로그인합니다 (admin / admin).

  2. Settings → Database Connections로 이동합니다.

  3. + Database를 클릭합니다.

  4. 목록에서 ClickHouse Connect를 선택합니다.

  5. 다음을 입력합니다:

    필드값
    Display NameNYC Taxi — ClickHouse Cloud
    HostClickHouse Cloud 호스트명 (.clickhouse_state에서)
    Port8443
    Databaseanalytics
    Usernamedefault
    PasswordClickHouse Cloud 비밀번호
    SSL활성화
  6. Test Connection을 클릭 — 녹색 성공 배너를 확인합니다.

  7. Connect를 클릭합니다.


Part 1 — 데이터셋 생성

데이터셋 1 — fact_trips (테이블 데이터셋)

사용처: Operations Command Center, Executive Weekly Report, Driver Quality Analytics, Capabilities Showcase

  1. Datasets → + Dataset으로 이동합니다.
  2. Database = NYC Taxi — ClickHouse Cloud, Schema = analytics, Table = fact_trips로 설정합니다.
  3. Add Dataset and Create Chart를 클릭 → 그다음 다른 곳으로 이동합니다 — 데이터셋은 저장되었습니다.

데이터셋 2 — agg_hourly_zone_trips (테이블 데이터셋)

사용처: Operations Command Center, Executive Weekly Report

  1. Datasets → + Dataset으로 이동합니다.
  2. Database = NYC Taxi — ClickHouse Cloud, Schema = analytics, Table = agg_hourly_zone_trips로 설정합니다.
  3. Save를 클릭합니다.

데이터셋 3 — CH Approx Unique Trips (uniqHLL12) (가상)

사용처: Capabilities Showcase — 정확한 uniq()와 비교해 uniqHLL12() 근사 카운팅을 보여줍니다.

  1. Datasets → + Dataset으로 이동합니다.
  2. Switch to SQL Lab을 클릭합니다(또는 Virtual 탭을 선택합니다).
  3. Database = NYC Taxi — ClickHouse Cloud로 설정합니다.
  4. SQL을 붙여넣습니다:
SELECT
  toDate(pickup_at)                                                     AS day,
  uniq(trip_id)                                                         AS exact_unique_trips,
  uniqHLL12(trip_id)                                                    AS approx_unique_trips,
  round(
    abs(uniq(trip_id) - uniqHLL12(trip_id)) / uniq(trip_id) * 100, 2
  )                                                                     AS pct_error
FROM analytics.fact_trips FINAL
WHERE pickup_at >= today() - INTERVAL 30 DAY
GROUP BY day
ORDER BY day
  1. 이름을 **CH Approx Unique Trips (uniqHLL12)**로 지정하고 Save를 클릭합니다.

데이터셋 4 — CH Cohort Retention (가상)

사용처: Capabilities Showcase — 자치구별 롤링 매출을 위한 윈도 함수(AVG(...) OVER (...))를 보여줍니다.

  1. Datasets → + Dataset → Virtual로 이동합니다.
  2. Database = NYC Taxi — ClickHouse Cloud로 설정합니다.
  3. SQL을 붙여넣습니다:
SELECT
  week,
  pickup_borough,
  trips,
  revenue,
  round(avg(revenue) OVER (
    PARTITION BY pickup_borough
    ORDER BY week
    ROWS BETWEEN 3 PRECEDING AND CURRENT ROW
  ), 2) AS rolling_4wk_avg_revenue
FROM (
  SELECT
    toStartOfWeek(pickup_at)       AS week,
    pickup_borough,
    count()                        AS trips,
    round(sum(fare_amount_usd), 2) AS revenue
  FROM analytics.fact_trips FINAL
  GROUP BY week, pickup_borough
)
ORDER BY week DESC, revenue DESC
LIMIT 100
  1. 이름을 **CH Cohort Retention**으로 지정하고 Save를 클릭합니다.

데이터셋 5 — CH Fare Percentiles (quantileTDigest) (가상)

사용처: Capabilities Showcase — ClickHouse 네이티브 백분위 함수로서 quantileTDigest()를 보여줍니다.

  1. Datasets → + Dataset → Virtual로 이동합니다.
  2. Database = NYC Taxi — ClickHouse Cloud로 설정합니다.
  3. SQL을 붙여넣습니다:
SELECT
  vendor_name,
  quantileTDigest(0.5)(fare_amount_usd)  AS p50_fare,
  quantileTDigest(0.95)(fare_amount_usd) AS p95_fare,
  quantileTDigest(0.99)(fare_amount_usd) AS p99_fare,
  count()                                AS trip_count
FROM analytics.fact_trips FINAL
GROUP BY vendor_name
ORDER BY vendor_name
  1. 이름을 **CH Fare Percentiles (quantileTDigest)**로 지정하고 Save를 클릭합니다.

데이터셋 6 — CH Sampling Demo (가상)

사용처: Capabilities Showcase — 전체 스캔과 비교해 rand() % N 샘플링의 정확도를 보여줍니다.

  1. Datasets → + Dataset → Virtual로 이동합니다.
  2. Database = NYC Taxi — ClickHouse Cloud로 설정합니다.
  3. SQL을 붙여넣습니다:
SELECT
  'Full Scan'              AS method,
  count()                  AS trip_count,
  round(avg(fare_amount_usd), 4) AS avg_fare
FROM analytics.fact_trips FINAL
UNION ALL
SELECT
  '~10% (rand() % 10 = 0)' AS method,
  count() * 10              AS trip_count_est,
  round(avg(fare_amount_usd), 4) AS avg_fare
FROM analytics.fact_trips FINAL
WHERE rand() % 10 = 0
  1. 이름을 **CH Sampling Demo**로 지정하고 Save를 클릭합니다.

데이터셋 7 — CH Zone Dict Lookup (가상)

사용처: Capabilities Showcase — JOIN 없는 차원 보강을 위한 dictGet()을 보여줍니다.

필요 조건: 7.4단계의 딕셔너리 analytics.taxi_zones_dict (scripts/04_create_dictionary.sql).

  1. Datasets → + Dataset → Virtual로 이동합니다.
  2. Database = NYC Taxi — ClickHouse Cloud로 설정합니다.
  3. SQL을 붙여넣습니다:
SELECT
  dictGet('analytics.taxi_zones_dict', 'borough', toUInt16(pickup_location_id)) AS borough,
  dictGet('analytics.taxi_zones_dict', 'zone',    toUInt16(pickup_location_id)) AS zone,
  count()                                                                        AS trips,
  round(avg(fare_amount_usd), 2)                                                 AS avg_fare
FROM default.trips_raw
WHERE pickup_at >= today() - INTERVAL 7 DAY
GROUP BY borough, zone
ORDER BY trips DESC
  1. 이름을 **CH Zone Dict Lookup**으로 지정하고 Save를 클릭합니다.

이 데이터셋은 사전 처리 없이 소스 계층에서 딕셔너리가 동작하는 것을 보여주기 위해 analytics.fact_trips가 아니라 default.trips_raw(원시 테이블)에서 읽습니다.


Part 2 — 차트 생성

Charts → + Chart로 차트를 만들고, 데이터셋을 선택하고, 차트 유형을 고르고, 필드를 구성한 뒤 명시된 이름 그대로 Save하세요.


대시보드 1 — CH Operations Command Center

차트: CH Total Trips Today

설정값
Datasetfact_trips
Chart typeBig Number
MetricCOUNT(trip_id)
Time filterpickup_at = today : now
Subheadertrips today

**CH Total Trips Today**로 저장합니다.

차트: CH Revenue Today

설정값
Datasetfact_trips
Chart typeBig Number
MetricSUM(fare_amount_usd)
Time filterpickup_at = today : now
Subheaderrevenue today

**CH Revenue Today**로 저장합니다.

차트: CH Trip Volume by Hour (24h)

설정값
Datasetagg_hourly_zone_trips
Chart typeLine Chart (ECharts)
X-axishour_bucket
MetricSUM(trips)
Time grain1 hour

**CH Trip Volume by Hour (24h)**로 저장합니다.

차트: CH Revenue by Zone (Top 10)

설정값
Datasetagg_hourly_zone_trips
Chart typeBar Chart
Dimensionszone_id
MetricSUM(revenue)
Row limit10
Sort bars활성화

**CH Revenue by Zone (Top 10)**로 저장합니다.


대시보드 2 — CH Executive Weekly Report

차트: CH Daily Revenue (7 days)

설정값
Datasetfact_trips
Chart typeLine Chart (ECharts)
X-axispickup_at
MetricSUM(fare_amount_usd)
Time grain1 hour

**CH Daily Revenue (7 days)**로 저장합니다.

차트: CH Top Zones by Revenue

설정값
Datasetagg_hourly_zone_trips
Chart typeBar Chart
Dimensionszone_id
MetricSUM(revenue)
Row limit20
Sort bars활성화

**CH Top Zones by Revenue**로 저장합니다.

차트: CH Payment Distribution

설정값
Datasetfact_trips
Chart typePie Chart
Dimensionspayment_type
MetricCOUNT(trip_id)

**CH Payment Distribution**으로 저장합니다.

차트: CH Avg Fare by Vendor

설정값
Datasetfact_trips
Chart typeBar Chart
Dimensionsvendor_name
MetricAVG(fare_amount_usd)
Row limit20
Sort bars활성화

**CH Avg Fare by Vendor**로 저장합니다.


대시보드 3 — CH Driver Quality Analytics

차트: CH Rating Distribution

설정값
Datasetfact_trips
Chart typeBar Chart
Dimensionsdriver_rating
MetricCOUNT(trip_id)
Row limit20
Sort bars활성화

**CH Rating Distribution**으로 저장합니다.

차트: CH High-Rated Driver Revenue

설정값
Datasetfact_trips
Chart typeBig Number
MetricSUM(fare_amount_usd)
Filterdriver_rating >= 4.5
Subheaderrevenue from 4.5+ rated drivers

**CH High-Rated Driver Revenue**로 저장합니다.

차트: CH Avg Fare by Driver Rating

설정값
Datasetfact_trips
Chart typeBar Chart
Dimensionsdriver_rating
MetricAVG(fare_amount_usd)
Row limit20
Sort bars활성화

**CH Avg Fare by Driver Rating**로 저장합니다.

차트: CH Top Drivers Leaderboard

설정값
Datasetfact_trips
Chart typeTable
Query modeRaw records
Columnsvendor_name, vehicle_type, driver_rating, fare_amount_usd
Row limit1000

**CH Top Drivers Leaderboard**로 저장합니다.


대시보드 4 — CH Capabilities Showcase

차트: CH Recent Trips (fact_trips)

설정값
Datasetfact_trips
Chart typeTable
Query modeRaw records
Columnstrip_id, pickup_at, dropoff_at, fare_amount_usd, pickup_borough, vendor_name
Row limit1000

**CH Recent Trips (fact_trips)**로 저장합니다.

차트: CH Fare Percentiles (quantileTDigest)

설정값
DatasetCH Fare Percentiles (quantileTDigest)
Chart typeTable
Query modeRaw records
Columnsvendor_name, p50_fare, p95_fare, p99_fare, trip_count

**CH Fare Percentiles (quantileTDigest)**로 저장합니다.

차트: CH Approx vs Exact Unique Trips (uniqHLL12)

설정값
DatasetCH Approx Unique Trips (uniqHLL12)
Chart typeTable
Query modeRaw records
Columnsday, exact_unique_trips, approx_unique_trips, pct_error

**CH Approx vs Exact Unique Trips (uniqHLL12)**로 저장합니다.

차트: CH Sampling Accuracy Demo (SAMPLE 0.1)

설정값
DatasetCH Sampling Demo
Chart typeTable
Query modeRaw records
Columnsmethod, trip_count, avg_fare

**CH Sampling Accuracy Demo (SAMPLE 0.1)**로 저장합니다.

차트: CH Zone Lookup via Dictionary (dictGet)

설정값
DatasetCH Zone Dict Lookup
Chart typeTable
Query modeRaw records
Columnsborough, zone, trips, avg_fare

**CH Zone Lookup via Dictionary (dictGet)**로 저장합니다.

차트: CH Weekly Revenue Trend (window functions)

설정값
DatasetCH Cohort Retention
Chart typeTable
Query modeRaw records
Columnsweek, pickup_borough, trips, revenue, rolling_4wk_avg_revenue

**CH Weekly Revenue Trend (window functions)**로 저장합니다.


Part 3 — 대시보드 조립

각 대시보드마다:

  1. Dashboards → + Dashboard로 이동합니다.
  2. 제목을 입력합니다.
  3. Save를 클릭한 다음 Edit Dashboard를 클릭합니다.
  4. 오른쪽 패널에서 각 차트를 캔버스로 드래그합니다.
  5. 완료하면 Save를 클릭합니다.

CH — Operations Command Center

제목: CH — Operations Command Center

행차트
행 1CH Total Trips Today · CH Revenue Today
행 2CH Trip Volume by Hour (24h) · CH Revenue by Zone (Top 10)

CH — Executive Weekly Report

제목: CH — Executive Weekly Report

행차트
행 1CH Daily Revenue (7 days) · CH Top Zones by Revenue · CH Payment Distribution · CH Avg Fare by Vendor

CH — Driver Quality Analytics

제목: CH — Driver Quality Analytics

행차트
행 1CH Rating Distribution · CH High-Rated Driver Revenue
행 2CH Avg Fare by Driver Rating · CH Top Drivers Leaderboard

CH — Capabilities Showcase

제목: CH — Capabilities Showcase

행차트
행 1CH Recent Trips (fact_trips) · CH Fare Percentiles (quantileTDigest)
행 2CH Approx vs Exact Unique Trips (uniqHLL12) · CH Sampling Accuracy Demo (SAMPLE 0.1)
행 3CH Zone Lookup via Dictionary (dictGet) · CH Weekly Revenue Trend (window functions)

검증

Part 3을 완료한 후 http://localhost:8088을 엽니다. Dashboards에서 총 7개가 보여야 합니다 — Snowflake 대시보드 3개(Part 1 설정에서)와 CH — 접두사가 붙은 4개입니다.


트러블슈팅

fact_trips 또는 agg_hourly_zone_trips를 찾을 수 없음 먼저 dbt run을 실행하세요(7.3단계).

dictGet이 빈 문자열을 반환함 analytics.taxi_zones_dict 딕셔너리가 생성되지 않았습니다. scripts/04_create_dictionary.sql을 실행하세요(7.4단계).

가상 데이터셋이 행을 반환하지 않음 일부 쿼리의 30일 / 7일 윈도우에는 최근 데이터가 필요합니다. 마이그레이션 데이터가 모두 과거 데이터라면 시간 필터를 고정 날짜로 교체하세요:

-- Replace: WHERE pickup_at >= today() - INTERVAL 30 DAY
-- With:    WHERE pickup_at >= '2023-01-01'

가져오기 스크립트에서 403 오류 Superset 세션 쿠키가 만료되었습니다. 로그아웃 후 다시 로그인하고 재실행하세요.

이 페이지의 내용

KO