يدعم ClickHouse التكامل مع عدة كتالوجات (Unity وGlue وREST وPolaris وغيرها). سيرشدك هذا الدليل خلال الخطوات اللازمة للاستعلام عن بياناتك باستخدام ClickHouse وكتالوج Lakekeeper.
Lakekeeper هو تنفيذ مفتوح المصدر لكتالوج REST لـ Apache Iceberg، ويوفّر ما يلي:
- تنفيذ Rust native لأداء عالٍ وموثوقية عالية
- امتثال REST API لمواصفة Iceberg REST كتالوج
- تكامل Cloud storage مع التخزين المتوافق مع S3
إعداد بيئة التطوير المحلية
للتطوير والاختبار محليًا، يمكنك استخدام إعداد Lakekeeper مُشغَّل داخل حاويات. يُعد هذا النهج مثاليًا للتعلّم، وإنشاء النماذج الأولية، وبيئات التطوير.
المتطلبات الأساسية
- Docker وDocker Compose: تأكد من أن Docker مثبّت ويعمل
- الإعداد النموذجي: يمكنك استخدام إعداد
docker-composeالخاص بـ Lakekeeper
إعداد كتالوج Lakekeeper المحلي
يمكنك استخدام إعداد docker-compose الرسمي لـ Lakekeeper، الذي يوفّر بيئة متكاملة تضم Lakekeeper، وخلفية بيانات وصفية لـ PostgreSQL، وMinIO لتخزين الكائنات.
الخطوة 1: أنشئ مجلدًا جديدًا لتشغيل المثال فيه، ثم أنشئ ملف docker-compose.yml بالتكوين التالي:
version: '3.8'
services:
lakekeeper:
image: quay.io/lakekeeper/catalog:latest
environment:
- LAKEKEEPER__PG_ENCRYPTION_KEY=This-is-NOT-Secure!
- LAKEKEEPER__PG_DATABASE_URL_READ=postgresql://postgres:postgres@db:5432/postgres
- LAKEKEEPER__PG_DATABASE_URL_WRITE=postgresql://postgres:postgres@db:5432/postgres
- RUST_LOG=info
command: ["serve"]
healthcheck:
test: ["CMD", "/home/nonroot/lakekeeper", "healthcheck"]
interval: 1s
timeout: 10s
retries: 10
start_period: 30s
depends_on:
migrate:
condition: service_completed_successfully
db:
condition: service_healthy
minio:
condition: service_healthy
ports:
- 8181:8181
networks:
- iceberg_net
migrate:
image: quay.io/lakekeeper/catalog:latest-main
environment:
- LAKEKEEPER__PG_ENCRYPTION_KEY=This-is-NOT-Secure!
- LAKEKEEPER__PG_DATABASE_URL_READ=postgresql://postgres:postgres@db:5432/postgres
- LAKEKEEPER__PG_DATABASE_URL_WRITE=postgresql://postgres:postgres@db:5432/postgres
- RUST_LOG=info
restart: "no"
command: ["migrate"]
depends_on:
db:
condition: service_healthy
networks:
- iceberg_net
bootstrap:
image: curlimages/curl
depends_on:
lakekeeper:
condition: service_healthy
restart: "no"
command:
- -w
- "%{http_code}"
- "-X"
- "POST"
- "-v"
- "http://lakekeeper:8181/management/v1/bootstrap"
- "-H"
- "Content-Type: application/json"
- "--data"
- '{"accept-terms-of-use": true}'
- "-o"
- "/dev/null"
networks:
- iceberg_net
initialwarehouse:
image: curlimages/curl
depends_on:
lakekeeper:
condition: service_healthy
bootstrap:
condition: service_completed_successfully
restart: "no"
command:
- -w
- "%{http_code}"
- "-X"
- "POST"
- "-v"
- "http://lakekeeper:8181/management/v1/warehouse"
- "-H"
- "Content-Type: application/json"
- "--data"
- '{"warehouse-name": "demo", "project-id": "00000000-0000-0000-0000-000000000000", "storage-profile": {"type": "s3", "bucket": "warehouse-rest", "key-prefix": "", "assume-role-arn": null, "endpoint": "http://minio:9000", "region": "local-01", "path-style-access": true, "flavor": "minio", "sts-enabled": true}, "storage-credential": {"type": "s3", "credential-type": "access-key", "aws-access-key-id": "minio", "aws-secret-access-key": "ClickHouse_Minio_P@ssw0rd"}}'
- "-o"
- "/dev/null"
networks:
- iceberg_net
db:
image: bitnami/postgresql:16.3.0
environment:
- POSTGRESQL_USERNAME=postgres
- POSTGRESQL_PASSWORD=postgres
- POSTGRESQL_DATABASE=postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -p 5432 -d postgres"]
interval: 2s
timeout: 10s
retries: 5
start_period: 10s
volumes:
- postgres_data:/bitnami/postgresql
networks:
- iceberg_net
minio:
image: bitnami/minio:2025.4.22
environment:
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD=ClickHouse_Minio_P@ssw0rd
- MINIO_API_PORT_NUMBER=9000
- MINIO_CONSOLE_PORT_NUMBER=9001
- MINIO_SCHEME=http
- MINIO_DEFAULT_BUCKETS=warehouse-rest
networks:
iceberg_net:
aliases:
- warehouse-rest.minio
ports:
- "9002:9000"
- "9003:9001"
healthcheck:
test: ["CMD", "mc", "ls", "local", "|", "grep", "warehouse-rest"]
interval: 2s
timeout: 10s
retries: 3
start_period: 15s
volumes:
- minio_data:/bitnami/minio/data
clickhouse:
image: clickhouse/clickhouse-server:head
container_name: lakekeeper-clickhouse
user: '0:0' # Ensures root permissions
ports:
- "8123:8123"
- "9000:9000"
volumes:
- clickhouse_data:/var/lib/clickhouse
- ./clickhouse/data_import:/var/lib/clickhouse/data_import # Mount dataset folder
networks:
- iceberg_net
environment:
- CLICKHOUSE_DB=default
- CLICKHOUSE_USER=default
- CLICKHOUSE_DO_NOT_CHOWN=1
- CLICKHOUSE_PASSWORD=
depends_on:
lakekeeper:
condition: service_healthy
minio:
condition: service_healthy
volumes:
postgres_data:
minio_data:
clickhouse_data:
networks:
iceberg_net:
driver: bridgeالخطوة 2: شغّل الأمر التالي لتشغيل الخدمات:
docker compose up -dالخطوة 3: انتظر حتى تصبح جميع الخدمات جاهزة. يمكنك الاطلاع على السجلات:
docker-compose logs -fالاتصال بـ كتالوج Lakekeeper المحلي
اتصل بحاوية ClickHouse لديك:
docker exec -it lakekeeper-clickhouse clickhouse-clientثم أنشئ اتصال قاعدة البيانات بـ كتالوج Lakekeeper:
SET allow_experimental_database_iceberg = 1;
CREATE DATABASE demo
ENGINE = DataLakeCatalog('http://lakekeeper:8181/catalog', 'minio', 'ClickHouse_Minio_P@ssw0rd')
SETTINGS catalog_type = 'rest', storage_endpoint = 'http://minio:9002/warehouse-rest', warehouse = 'demo'الاستعلام عن جداول كتالوج Lakekeeper باستخدام ClickHouse
الآن بعد إعداد الاتصال، يمكنك البدء في الاستعلام عبر كتالوج Lakekeeper. على سبيل المثال:
USE demo;
SHOW TABLES;إذا كان إعدادك يتضمن بيانات تجريبية (مثل مجموعة بيانات سيارات الأجرة)، فيُفترض أن ترى جداول مثل:
┌─name──────────┐
│ default.taxis │
└───────────────┘لاستعلام أحد الجداول (إذا كان متاحًا):
SELECT count(*) FROM `default.taxis`;┌─count()─┐
│ 2171187 │
└─────────┘لفحص DDL للجدول:
SHOW CREATE TABLE `default.taxis`;┌─statement─────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE demo.`default.taxis` │
│ ( │
│ `VendorID` Nullable(Int64), │
│ `tpep_pickup_datetime` Nullable(DateTime64(6)), │
│ `tpep_dropoff_datetime` Nullable(DateTime64(6)), │
│ `passenger_count` Nullable(Float64), │
│ `trip_distance` Nullable(Float64), │
│ `RatecodeID` Nullable(Float64), │
│ `store_and_fwd_flag` Nullable(String), │
│ `PULocationID` Nullable(Int64), │
│ `DOLocationID` Nullable(Int64), │
│ `payment_type` Nullable(Int64), │
│ `fare_amount` Nullable(Float64), │
│ `extra` Nullable(Float64), │
│ `mta_tax` Nullable(Float64), │
│ `tip_amount` Nullable(Float64), │
│ `tolls_amount` Nullable(Float64), │
│ `improvement_surcharge` Nullable(Float64), │
│ `total_amount` Nullable(Float64), │
│ `congestion_surcharge` Nullable(Float64), │
│ `airport_fee` Nullable(Float64) │
│ ) │
│ ENGINE = Iceberg('http://minio:9002/warehouse-rest/warehouse/default/taxis/', 'minio', '[HIDDEN]') │
└───────────────────────────────────────────────────────────────────────────────────────────────┘تحميل البيانات من بحيرة البيانات لديك إلى ClickHouse
إذا كنت بحاجة إلى تحميل البيانات من كتالوج Lakekeeper إلى ClickHouse، فابدأ بإنشاء جدول ClickHouse محلي:
CREATE TABLE taxis
(
`VendorID` Int64,
`tpep_pickup_datetime` DateTime64(6),
`tpep_dropoff_datetime` DateTime64(6),
`passenger_count` Float64,
`trip_distance` Float64,
`RatecodeID` Float64,
`store_and_fwd_flag` String,
`PULocationID` Int64,
`DOLocationID` Int64,
`payment_type` Int64,
`fare_amount` Float64,
`extra` Float64,
`mta_tax` Float64,
`tip_amount` Float64,
`tolls_amount` Float64,
`improvement_surcharge` Float64,
`total_amount` Float64,
`congestion_surcharge` Float64,
`airport_fee` Float64
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(tpep_pickup_datetime)
ORDER BY (VendorID, tpep_pickup_datetime, PULocationID, DOLocationID);ثم حمّل البيانات من جدولك في كتالوج Lakekeeper باستخدام INSERT INTO SELECT:
INSERT INTO taxis
SELECT * FROM demo.`default.taxis`;