Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

ClickHouse Managed Postgres 빠른 시작

베타

ClickHouse Managed Postgres는 NVMe 스토리지를 기반으로 하는 엔터프라이즈급 Postgres로, EBS와 같은 네트워크 연결 스토리지 대비 디스크 입출력에 병목이 있는 워크로드에서 최대 10배 빠른 성능을 제공합니다. 이 quickstart는 두 부분으로 구성됩니다:

  • 파트 1: NVMe Postgres 시작하기 및 성능 체험하기
  • 파트 2: ClickHouse와 통합해 실시간 분석 시작하기

ClickHouse Managed Postgres는 현재 AWS의 여러 리전에서 사용 가능하며, 퍼블릭 베타 단계입니다.

이 퀵스타트에서 수행할 작업:

  • NVMe 기반 고성능 ClickHouse Managed Postgres 인스턴스를 생성하세요
  • 100만 개의 샘플 이벤트를 적재하고 NVMe 속도를 직접 확인하세요
  • 쿼리를 실행하고 낮은 지연 시간의 성능을 체험하세요
  • 실시간 분석을 위해 데이터를 ClickHouse로 복제하세요
  • pg_clickhouse를 사용해 Postgres에서 ClickHouse를 직접 쿼리하세요

1부: NVMe Postgres 시작하기

데이터베이스 생성

새로운 ClickHouse Managed Postgres 서비스를 생성하려면 Cloud Console의 서비스 목록에서 New service 버튼을 클릭하십시오. 이후 데이터베이스 유형으로 Postgres를 선택할 수 있습니다.

ClickHouse Managed Postgres 서비스 생성

데이터베이스 인스턴스의 이름을 입력하고 Create service를 클릭합니다. 개요(Overview) 페이지로 이동합니다.

ClickHouse Managed Postgres 개요

ClickHouse 관리형 Postgres 인스턴스는 3~5분 내에 프로비저닝되어 사용 가능한 상태가 됩니다.

데이터베이스에 연결하기

왼쪽 사이드바에서 Connect 버튼을 확인할 수 있습니다. 이 버튼을 클릭하면 접속 정보와 다양한 포맷의 연결 문자열(connection string)을 확인할 수 있습니다.

ClickHouse Managed Postgres 연결 창

psql 연결 문자열을 복사하여 데이터베이스에 연결하세요. DBeaver와 같은 Postgres 호환 클라이언트나 애플리케이션 라이브러리도 사용할 수 있습니다.

NVMe 성능 직접 체험하기

NVMe 기반 성능이 실제로 어느 정도인지 확인해 보겠습니다. 먼저 쿼리 실행 시간을 측정할 수 있도록 psql에서 타이밍을 활성화합니다:

\

이벤트와 사용자용 샘플 테이블 2개를 생성합니다:

CREATE TABLE events (
   event_id SERIAL PRIMARY KEY,
   event_name VARCHAR(255) NOT NULL,
   event_type VARCHAR(100),
   event_timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
   event_data JSONB,
   user_id INT,
   user_ip INET,
   is_active BOOLEAN DEFAULT TRUE,
   created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
   updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE users (
   user_id SERIAL PRIMARY KEY,
   name VARCHAR(100),
   country VARCHAR(50),
   platform VARCHAR(50)
);

이제 이벤트 100만 개를 삽입한 뒤 NVMe 속도를 확인해 보세요:

INSERT INTO events (event_name, event_type, event_timestamp, event_data, user_id, user_ip)
SELECT
   'Event ' || gs::text AS event_name,
   CASE
       WHEN random() < 0.5 THEN 'click'
       WHEN random() < 0.75 THEN 'view'
       WHEN random() < 0.9 THEN 'purchase'
       WHEN random() < 0.98 THEN 'signup'
       ELSE 'logout'
   END AS event_type,
   NOW() - INTERVAL '1 day' * (gs % 365) AS event_timestamp,
   jsonb_build_object('key', 'value' || gs::text, 'additional_info', 'info_' || (gs % 100)::text) AS event_data,
   GREATEST(1, LEAST(1000, FLOOR(POWER(random(), 2) * 1000) + 1)) AS user_id,
   ('192.168.1.' || ((gs % 254) + 1))::inet AS user_ip
FROM
   generate_series(1, 1000000) gs;
INSERT 0 1000000
Time: 3596.542 ms (00:03.597)

사용자 1,000명을 삽입합니다:

INSERT INTO users (name, country, platform)
SELECT
    first_names[first_idx] || ' ' || last_names[last_idx] AS name,
    CASE
        WHEN random() < 0.25 THEN 'India'
        WHEN random() < 0.5 THEN 'USA'
        WHEN random() < 0.7 THEN 'Germany'
        WHEN random() < 0.85 THEN 'China'
        ELSE 'Other'
    END AS country,
    CASE
        WHEN random() < 0.2 THEN 'iOS'
        WHEN random() < 0.4 THEN 'Android'
        WHEN random() < 0.6 THEN 'Web'
        WHEN random() < 0.75 THEN 'Windows'
        WHEN random() < 0.9 THEN 'MacOS'
        ELSE 'Linux'
    END AS platform
FROM
    generate_series(1, 1000) AS seq
    CROSS JOIN LATERAL (
        SELECT
            array['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Hank', 'Ivy', 'Jack', 'Liam', 'Olivia', 'Noah', 'Emma', 'Sophia', 'Benjamin', 'Isabella', 'Lucas', 'Mia', 'Amelia', 'Aarav', 'Riya', 'Arjun', 'Ananya', 'Wei', 'Li', 'Huan', 'Mei', 'Hans', 'Klaus', 'Greta', 'Sofia'] AS first_names,
            array['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Martinez', 'Taylor', 'Anderson', 'Thomas', 'Jackson', 'White', 'Harris', 'Martin', 'Thompson', 'Moore', 'Lee', 'Perez', 'Sharma', 'Patel', 'Gupta', 'Reddy', 'Zhang', 'Wang', 'Chen', 'Liu', 'Schmidt', 'Müller', 'Weber', 'Fischer'] AS last_names,
            1 + (seq % 32) AS first_idx,
            1 + ((seq / 32)::int % 32) AS last_idx
    ) AS names;

데이터에 쿼리 실행하기

이제 몇 가지 쿼리를 실행해 NVMe 스토리지에서 Postgres가 얼마나 빠르게 응답하는지 확인해 보겠습니다.

이벤트 100만 개를 유형별로 집계합니다:

SELECT event_type, COUNT(*) as count 
FROM events 
GROUP BY event_type 
ORDER BY count DESC;
 event_type | count  
------------+--------
 click      | 499523
 view       | 375644
 purchase   | 112473
 signup     |  12117
 logout     |    243
(5 rows)

Time: 114.883 ms

JSONB 필터링 및 날짜 범위를 활용한 쿼리:

SELECT COUNT(*) 
FROM events 
WHERE event_timestamp > NOW() - INTERVAL '30 days'
  AND event_data->>'additional_info' LIKE 'info_5%';
 count 
-------
  9042
(1 row)

Time: 109.294 ms

이벤트와 사용자 조인(join):

SELECT u.country, COUNT(*) as events, AVG(LENGTH(e.event_data::text))::int as avg_json_size
FROM events e
JOIN users u ON e.user_id = u.user_id
GROUP BY u.country
ORDER BY events DESC;
 country | events | avg_json_size 
---------+--------+---------------
 USA     | 383748 |            52
 India   | 255990 |            52
 Germany | 223781 |            52
 China   | 127754 |            52
 Other   |   8727 |            52
(5 rows)

Time: 224.670 ms

Part 2: ClickHouse로 실시간 분석 추가하기

Postgres는 트랜잭션 워크로드(OLTP)에 탁월하고, ClickHouse는 대규모 데이터셋에 대한 분석 쿼리(OLAP)를 위해 특별히 설계되었습니다. 두 시스템을 통합하면 양쪽의 장점을 모두 활용할 수 있습니다:

  • 애플리케이션의 트랜잭션 데이터(삽입, 업데이트, 단건 조회)용 Postgres
  • 수십억 개의 행을 1초 이내에 분석할 수 있는 ClickHouse

이 섹션에서는 Postgres 데이터를 ClickHouse로 복제하고 원활하게 쿼리하는 방법을 설명합니다.

ClickHouse 통합 설정

이제 Postgres에 테이블과 데이터가 준비되었으니, 분석을 위해 테이블을 ClickHouse로 복제해 보겠습니다. 사이드바에서 Sync to ClickHouse를 클릭한 다음, Replicate data in ClickHouse를 클릭하십시오.

ClickHouse Managed Postgres 통합이 비어 있습니다

다음 양식에서 통합의 이름을 입력하고 데이터를 복제할 기존 ClickHouse 인스턴스를 선택할 수 있습니다. ClickHouse 인스턴스가 아직 없는 경우, 이 양식에서 직접 생성할 수 있습니다.

ClickHouse Managed Postgres 통합 양식

다음을 클릭하면 테이블 선택기로 이동합니다. 여기서 필요한 작업은 다음과 같습니다:

  • 복제할 ClickHouse 데이터베이스를 선택합니다.
  • public 스키마를 펼친 다음, 앞서 생성한 users 테이블과 events 테이블을 선택합니다.
  • Replicate data to ClickHouse를 클릭합니다.
ClickHouse Managed Postgres 테이블 선택기

복제 프로세스가 시작되며 통합 개요 페이지로 이동합니다. 첫 번째 통합인 경우 초기 인프라를 설정하는 데 2~3분이 소요될 수 있습니다. 그동안 새로운 pg_clickhouse 확장 기능을 살펴보겠습니다.

Postgres에서 ClickHouse 쿼리하기

pg_clickhouse 확장 기능을 사용하면 표준 SQL로 Postgres에서 직접 ClickHouse 데이터를 쿼리할 수 있습니다. 즉, 애플리케이션이 트랜잭션 데이터와 분석 데이터 모두에 대해 Postgres를 통합 쿼리 레이어로 활용할 수 있습니다. 자세한 내용은 전체 문서를 참조하십시오.

확장 기능을 활성화합니다:

CREATE EXTENSION pg_clickhouse;

다음으로, ClickHouse에 대한 외부 서버 연결을 생성합니다. 보안 연결에는 포트 8443http 드라이버를 사용하십시오:

CREATE SERVER ch FOREIGN DATA WRAPPER clickhouse_fdw
       OPTIONS(driver 'http', host '<clickhouse_cloud_host>', dbname '<database_name>', port '8443');

<clickhouse_cloud_host>를 ClickHouse 호스트명으로, <database_name>을 복제 설정 시 선택한 데이터베이스 이름으로 대체하십시오. 호스트명은 사이드바에서 Connect를 클릭하여 ClickHouse 서비스에서 확인할 수 있습니다.

ClickHouse 호스트 가져오기

이제 Postgres 사용자를 ClickHouse 서비스 자격 증명에 매핑합니다:

CREATE USER MAPPING FOR CURRENT_USER SERVER ch 
OPTIONS (user 'default', password '<clickhouse_password>');

이제 ClickHouse 테이블을 Postgres 스키마로 가져옵니다:

CREATE SCHEMA organization;
IMPORT FOREIGN SCHEMA "<database_name>" FROM SERVER ch INTO organization;

<database_name>을 서버 생성 시 사용한 데이터베이스 이름으로 대체하십시오.

이제 Postgres 클라이언트에서 ClickHouse 테이블을 모두 확인할 수 있습니다:

\

분석 기능을 직접 확인해 보세요

통합 페이지로 돌아가 확인해 보세요. 초기 복제가 완료된 것을 확인할 수 있습니다. 통합 이름을 클릭하면 세부 정보를 볼 수 있습니다.

ClickHouse Managed Postgres 분석 목록

서비스 이름을 클릭하여 ClickHouse 콘솔을 열고 복제된 테이블을 확인하십시오.

ClickHouse의 ClickHouse Managed Postgres 복제 테이블

Postgres와 ClickHouse 성능 비교

이제 몇 가지 분석 쿼리를 실행하여 Postgres와 ClickHouse 간의 성능을 비교해 보겠습니다. 복제된 테이블은 public_<table_name> 명명 규칙을 사용한다는 점에 유의하십시오.

쿼리 1: 활동량 기준 상위 사용자

이 쿼리는 여러 집계 결과를 사용해 가장 활발하게 활동하는 사용자를 찾습니다:

-- Via ClickHouse
SELECT 
    user_id,
    COUNT(*) as total_events,
    COUNT(DISTINCT event_type) as unique_event_types,
    SUM(CASE WHEN event_type = 'purchase' THEN 1 ELSE 0 END) as purchases,
    MIN(event_timestamp) as first_event,
    MAX(event_timestamp) as last_event
FROM organization.public_events
GROUP BY user_id
ORDER BY total_events DESC
LIMIT 10;
 user_id | total_events | unique_event_types | purchases |        first_event         |         last_event         
---------+--------------+--------------------+-----------+----------------------------+----------------------------
       1 |        31439 |                  5 |      3551 | 2025-01-22 22:40:45.612281 | 2026-01-21 22:40:45.612281
       2 |        13235 |                  4 |      1492 | 2025-01-22 22:40:45.612281 | 2026-01-21 22:40:45.612281
...
(10 rows)

Time: 163.898 ms   -- ClickHouse
Time: 554.621 ms   -- Same query on Postgres

쿼리 2: 국가 및 플랫폼별 사용자 참여도

이 쿼리는 이벤트와 사용자를 조인하여 참여 메트릭을 계산합니다:

-- Via ClickHouse
SELECT 
    u.country,
    u.platform,
    COUNT(DISTINCT e.user_id) as users,
    COUNT(*) as total_events,
    ROUND(COUNT(*)::numeric / COUNT(DISTINCT e.user_id), 2) as events_per_user,
    SUM(CASE WHEN e.event_type = 'purchase' THEN 1 ELSE 0 END) as purchases
FROM organization.public_events e
JOIN organization.public_users u ON e.user_id = u.user_id
GROUP BY u.country, u.platform
ORDER BY total_events DESC
LIMIT 10;
 country | platform | users | total_events | events_per_user | purchases 
---------+----------+-------+--------------+-----------------+-----------
 USA     | Android  |   115 |       109977 |             956 |     12388
 USA     | Web      |   108 |       105057 |             972 |     11847
 USA     | iOS      |    83 |        84594 |            1019 |      9565
 Germany | Android  |    85 |        77966 |             917 |      8852
 India   | Android  |    80 |        68095 |             851 |      7724
...
(10 rows)

Time: 170.353 ms   -- ClickHouse
Time: 1245.560 ms  -- Same query on Postgres

성능 비교:

쿼리 Postgres (NVMe) ClickHouse (via pg_clickhouse) 속도 향상
상위 사용자(집계 5개) 555 ms 164 ms 3.4x
사용자 참여도 (JOIN + 집계) 1,246 ms 170 ms 7.3x

정리

이 빠른 시작에서 생성한 리소스를 삭제하려면 다음을 실행하십시오:

  1. 먼저 ClickHouse 서비스에서 ClickPipe 통합을 삭제하십시오
  2. 그런 다음 Cloud Console에서 ClickHouse Managed Postgres 인스턴스를 삭제하십시오
베타

이 경로를 직접 따라 해도 되고, 스크립트로 자동화해도 되며, AI agent에 맡겨도 됩니다. 콘솔 버전은 Cloud UI 보기로 전환하세요.

이 페이지에서는 ClickHouse CLI (clickhousectl)와 psql을 사용해 명령줄에서 ClickHouse Managed Postgres를 Provisioning하고, 데이터를 적재하고, 이를 ClickHouse로 복제한 뒤 쿼리하는 방법을 설명합니다. 모든 명령은 비대화형이며, clickhousectl--json 옵션을 사용하면 JSON을 출력합니다.

사전 요구 사항

ClickHouse CLI를 설치합니다:

curl https://clickhouse.com/cli | sh

psql(PostgreSQL 클라이언트 도구, macOS에서는 brew install libpq)와 jq도 필요합니다.

쓰기 작업(생성, 삭제)에는 API Key 인증이 필요하고, OAuth 로그인은 읽기 전용입니다:

clickhousectl cloud auth login --api-key <YOUR_KEY> --api-secret <YOUR_SECRET>

또는 CLICKHOUSE_CLOUD_API_KEYCLICKHOUSE_CLOUD_API_SECRET 환경 변수를 설정하십시오. clickhousectl cloud auth status로 확인했을 때 범위가 read/write인 항목이 표시되어야 합니다.

Part 1: Postgres 생성 및 데이터 적재

Postgres 서비스 생성

서비스를 생성한 후 응답을 저장하십시오. 비밀번호는 한 번만 표시됩니다:

clickhousectl cloud postgres create \
  --name quickstart-pg \
  --region us-east-1 \
  --size m6gd.large \
  --pg-version 18 \
  --json > pg.json

응답에는 서비스 ID, 호스트명, 그리고 바로 사용할 수 있는 connection string이 포함됩니다:

{
  "id": "3b5a3112-bf02-82d0-bd02-fbe67d5caa7a",
  "name": "quickstart-pg",
  "provider": "aws",
  "region": "us-east-1",
  "postgresVersion": "18",
  "size": "m6gd.large",
  "storageSize": 118,
  "haType": "none",
  "state": "creating",
  "createdAt": "2026-07-22T13:21:22Z",
  "hostname": "quickstart-pg-c1406b50.pg7dd324nz0a1qm1fqskxbjn7m.c0.us-east-1.aws.pg.clickhouse.cloud",
  "username": "postgres",
  "password": "vV6cfEr2p_-TzkCDrZOx",
  "connectionString": "postgres://postgres:vV6cfEr2p_-TzkCDrZOx@quickstart-pg-c1406b50.pg7dd324nz0a1qm1fqskxbjn7m.c0.us-east-1.aws.pg.clickhouse.cloud:5432/postgres?channel_binding=require",
  "isPrimary": true,
  "tags": []
}

이 가이드의 나머지 부분에 필요한 정보를 추출합니다:

PG_ID=$(jq -r .id pg.json)
PG_URL=$(jq -r .connectionString pg.json)

비밀번호를 분실한 경우 clickhousectl cloud postgres reset-password $PG_ID --generate 명령으로 새 비밀번호를 생성하세요.

서비스 Provisioning이 완료될 때까지 기다리기

Provisioning에는 몇 분 정도 소요됩니다. 상태가 running이 될 때까지 폴링하세요:

while [ "$(clickhousectl cloud postgres get "$PG_ID" --json | jq -r .state)" != "running" ]; do
  sleep 15
done

샘플 데이터 Load

두 개의 테이블을 생성하고 psql을 사용해 이벤트 100만 건을 삽입합니다:

psql "$PG_URL" <<'SQL'
\timing
CREATE TABLE events (
   event_id SERIAL PRIMARY KEY,
   event_name VARCHAR(255) NOT NULL,
   event_type VARCHAR(100),
   event_timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
   event_data JSONB,
   user_id INT,
   user_ip INET,
   is_active BOOLEAN DEFAULT TRUE,
   created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
   updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE users (
   user_id SERIAL PRIMARY KEY,
   name VARCHAR(100),
   country VARCHAR(50),
   platform VARCHAR(50)
);

INSERT INTO events (event_name, event_type, event_timestamp, event_data, user_id, user_ip)
SELECT
   'Event ' || gs::text AS event_name,
   CASE
       WHEN random() < 0.5 THEN 'click'
       WHEN random() < 0.75 THEN 'view'
       WHEN random() < 0.9 THEN 'purchase'
       WHEN random() < 0.98 THEN 'signup'
       ELSE 'logout'
   END AS event_type,
   NOW() - INTERVAL '1 day' * (gs % 365) AS event_timestamp,
   jsonb_build_object('key', 'value' || gs::text, 'additional_info', 'info_' || (gs % 100)::text) AS event_data,
   GREATEST(1, LEAST(1000, FLOOR(POWER(random(), 2) * 1000) + 1)) AS user_id,
   ('192.168.1.' || ((gs % 254) + 1))::inet AS user_ip
FROM
   generate_series(1, 1000000) gs;

INSERT INTO users (name, country, platform)
SELECT
    first_names[first_idx] || ' ' || last_names[last_idx] AS name,
    CASE
        WHEN random() < 0.25 THEN 'India'
        WHEN random() < 0.5 THEN 'USA'
        WHEN random() < 0.7 THEN 'Germany'
        WHEN random() < 0.85 THEN 'China'
        ELSE 'Other'
    END AS country,
    CASE
        WHEN random() < 0.2 THEN 'iOS'
        WHEN random() < 0.4 THEN 'Android'
        WHEN random() < 0.6 THEN 'Web'
        WHEN random() < 0.75 THEN 'Windows'
        WHEN random() < 0.9 THEN 'MacOS'
        ELSE 'Linux'
    END AS platform
FROM
    generate_series(1, 1000) AS seq
    CROSS JOIN LATERAL (
        SELECT
            array['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Hank', 'Ivy', 'Jack', 'Liam', 'Olivia', 'Noah', 'Emma', 'Sophia', 'Benjamin', 'Isabella', 'Lucas', 'Mia', 'Amelia', 'Aarav', 'Riya', 'Arjun', 'Ananya', 'Wei', 'Li', 'Huan', 'Mei', 'Hans', 'Klaus', 'Greta', 'Sofia'] AS first_names,
            array['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Martinez', 'Taylor', 'Anderson', 'Thomas', 'Jackson', 'White', 'Harris', 'Martin', 'Thompson', 'Moore', 'Lee', 'Perez', 'Sharma', 'Patel', 'Gupta', 'Reddy', 'Zhang', 'Wang', 'Chen', 'Liu', 'Schmidt', 'Müller', 'Weber', 'Fischer'] AS last_names,
            1 + (seq % 32) AS first_idx,
            1 + ((seq / 32)::int % 32) AS last_idx
    ) AS names;
SQL
Timing is on.
CREATE TABLE
Time: 86.029 ms
CREATE TABLE
Time: 80.962 ms
INSERT 0 1000000
Time: 7120.357 ms (00:07.120)
INSERT 0 1000
Time: 84.807 ms

NVMe 스토리지 덕분에 m6gd.large(가장 작은 사양)에서는 100만 행 삽입이 약 7초 만에 완료됩니다. 쿼리로 확인하세요. 데이터는 random()으로 생성되므로 실행할 때마다 행 수가 달라집니다:

psql "$PG_URL" -c "SELECT event_type, COUNT(*) FROM events GROUP BY event_type ORDER BY 2 DESC;"

파트 2: ClickHouse로 복제하기

ClickHouse 서비스 생성

같은 리전에 서비스를 생성하고 응답을 저장하십시오. 비밀번호는 생성 시 응답에만 표시됩니다:

clickhousectl cloud service create \
  --name quickstart-ch \
  --region us-east-1 \
  --json > ch.json

CH_ID=$(jq -r .service.id ch.json)
CH_PASSWORD=$(jq -r .password ch.json)

실행 중이 될 때까지 기다리세요; ClickPipe에는 실행 중인 대상이 필요합니다:

while [ "$(clickhousectl cloud service get "$CH_ID" --json | jq -r .state)" != "running" ]; do
  sleep 15
done

대신 기존 서비스를 사용하려면 clickhousectl cloud service list에서 CH_ID를 설정하고, pg_clickhouse 단계에 필요한 해당 서비스의 default 사용자 password를 CH_PASSWORD로 설정하십시오.

테이블을 ClickHouse로 복제

ClickHouse 서비스에서 ClickHouse Managed Postgres 호스트명을 대상으로 Postgres CDC ClickPipe를 생성하세요. 이 파이프는 기존 행을 복사한 후, 이후 발생하는 변경 사항도 반영하여 ClickHouse와 계속 동기화합니다:

PG_HOST=$(jq -r .hostname pg.json)
PG_PASSWORD=$(jq -r .password pg.json)

clickhousectl cloud clickpipe create postgres "$CH_ID" \
  --name quickstart-sync \
  --host "$PG_HOST" \
  --pg-database postgres \
  --username postgres \
  --password "$PG_PASSWORD" \
  --table-mapping public.events:public_events \
  --table-mapping public.users:public_users \
  --json > pipe.json

PIPE_ID=$(jq -r .id pipe.json)

참고:

  • 복제된 테이블(Replicated Tables)은 --table-mapping 대상 이름으로 ClickHouse 서비스의 default 데이터베이스에 생성됩니다
  • publication과 replication slot은 자동으로 생성되며, publication은 매핑된 테이블 범위로 설정됩니다. 직접 관리하는 publication을 사용하려면 --publication-name을 전달하세요
  • Postgres의 직접 호스트명을 사용하세요. PgBouncer를 통한 복제는 지원되지 않습니다

파이프가 Running 상태가 될 때까지 기다리기

파이프는 Running 상태가 되기 전에 Provisioning, Setup, 그리고 (테이블이 큰 경우) Snapshot 단계를 거칩니다. 서비스에서 첫 번째 파이프가 Running 상태에 도달하는 데는 약 4분이 걸립니다. FailedInternalError는 최종 상태입니다:

while :; do
  STATE=$(clickhousectl cloud clickpipe get "$CH_ID" "$PIPE_ID" --json | jq -r .state)
  case "$STATE" in
    Running) break ;;
    Failed|InternalError) echo "ClickPipe entered terminal state: $STATE" >&2; exit 1 ;;
  esac
  sleep 15
done

ClickHouse에서 복제된 데이터 쿼리하기

CLI에서 ClickHouse 서비스에 직접 SQL을 실행합니다. 처음 호출하면 Query API 엔드포인트와 서비스 범위의 API Key가 자동으로 프로비저닝됩니다:

clickhousectl cloud service query --id "$CH_ID" \
  --query "SELECT count() FROM public_events"
Provisioning Query API endpoint + key for service 'quickstart-ch'...
1000000

Postgres에 새로 기록되는 데이터는 지속적으로 복제됩니다. 행을 삽입한 다음 개수가 1,000,001이 될 때까지 폴링하세요(일반적으로 1분 이내).

psql "$PG_URL" -c "INSERT INTO events (event_name, event_type, user_id, user_ip) VALUES ('cdc-test', 'click', 42, '10.0.0.1');"

while [ "$(clickhousectl cloud service query --id "$CH_ID" \
  --query "SELECT count() FROM public_events")" != "1000001" ]; do
  sleep 10
done

Postgres에서 ClickHouse 쿼리하기

pg_clickhouse 확장 기능을 사용하면 Postgres를 트랜잭션 데이터와 분석 데이터를 모두 아우르는 통합 쿼리 계층으로 사용할 수 있습니다. 먼저 ClickHouse HTTPS 호스트명을 확인한 다음, psql에서 확장 기능을 설정하십시오:

CH_HOST=$(clickhousectl cloud service get "$CH_ID" --json \
  | jq -r '.endpoints[] | select(.protocol=="https") | .host')

psql "$PG_URL" <<SQL
CREATE EXTENSION pg_clickhouse;
CREATE SERVER ch FOREIGN DATA WRAPPER clickhouse_fdw
       OPTIONS(driver 'http', host '$CH_HOST', dbname 'default', port '8443');
CREATE USER MAPPING FOR CURRENT_USER SERVER ch
       OPTIONS (user 'default', password '$CH_PASSWORD');
CREATE SCHEMA organization;
IMPORT FOREIGN SCHEMA "default" FROM SERVER ch INTO organization;
SQL

Heredoc은 의도적으로 따옴표로 감싸지 않았으므로, SQL이 Postgres에 전달되기 전에 셸이 $CH_HOST$CH_PASSWORD를 치환합니다. 이제 복제된 테이블이 organization 스키마의 외부 테이블(foreign table)로 표시되며, 해당 테이블에 대한 쿼리는 ClickHouse에서 실행됩니다.

이 데이터셋을 사용해 m6gd.large에서 측정한 결과, 분석 쿼리는 외부 테이블을 통해 실행할 때 6~9배 더 빠르게 실행됩니다(예: 5개 집계 GROUP BY는 ClickHouse 경유 시 176ms, 로컬에서는 1,133ms이며, 집계가 포함된 JOIN은 298ms 대 2,764ms입니다).

정리

먼저 ClickPipe를 삭제한 다음 Postgres 서비스를 삭제하십시오. 서비스를 삭제하면 해당 서비스의 모든 데이터가 영구적으로 삭제됩니다:

clickhousectl cloud clickpipe delete "$CH_ID" "$PIPE_ID"
clickhousectl cloud postgres delete "$PG_ID"

실행 중인 ClickHouse 서비스는 바로 삭제할 수 없습니다. 먼저 중지하고 stopped 상태가 될 때까지 기다린 다음 삭제하세요:

clickhousectl cloud service stop "$CH_ID"

while [ "$(clickhousectl cloud service get "$CH_ID" --json | jq -r .state)" != "stopped" ]; do
  sleep 10
done

clickhousectl cloud service delete "$CH_ID"
Navigation