في الأدلة السابقة، أجريتَ استعلامات على تنسيقات الجداول المفتوحة في مكانها، وحمّلتَ البيانات إلى MergeTree لإجراء تحليلات سريعة. وفي كثير من البنى المعمارية، تحتاج البيانات أيضًا إلى التدفق في الاتجاه المعاكس، من ClickHouse عائدةً إلى تنسيقات الجداول المفتوحة. وهناك سيناريوهان شائعان يدفعان إلى ذلك:
- نقل البيانات إلى التخزين طويل الأمد - تصل البيانات إلى ClickHouse بوصفها طبقة تحليلات فورية، تُغذّي لوحات المعلومات والتقارير التشغيلية. وبمجرد أن تتجاوز البيانات نافذتها الزمنية الفورية، يمكن كتابتها إلى Iceberg في التخزين الكائني للاحتفاظ بها بصورة دائمة وبتكلفة منخفضة وبتنسيق قابل للتشغيل البيني.
- ETL العكسي - تنتج التحويلات وعمليات التجميع والإثراء التي تُنفَّذ داخل ClickHouse مجموعات بيانات مشتقة تحتاج الأدوات اللاحقة والفرق الأخرى إلى استهلاكها. وتؤدي كتابة هذه النتائج إلى جداول Iceberg إلى إتاحتها عبر منظومة البيانات الأوسع.
في كلتا الحالتين، يتيح لك INSERT INTO SELECT نقل البيانات من جداول ClickHouse إلى جداول Iceberg المخزنة في التخزين الكائني.
إعداد مجموعة بيانات كمصدر
في هذا الدليل، سنستخدم مجموعة البيانات UK Price Paid — وهي سجل عام يتضمن كل معاملة بيع لعقار سكني في إنجلترا وويلز.
أنشئ جدول MergeTree واملأه
CREATE DATABASE uk;
CREATE TABLE uk.uk_price_paid
(
price UInt32,
date Date,
postcode1 LowCardinality(String),
postcode2 LowCardinality(String),
type Enum8('terraced' = 1, 'semi-detached' = 2, 'detached' = 3, 'flat' = 4, 'other' = 0),
is_new UInt8,
duration Enum8('freehold' = 1, 'leasehold' = 2, 'unknown' = 0),
addr1 String,
addr2 String,
street LowCardinality(String),
locality LowCardinality(String),
town LowCardinality(String),
district LowCardinality(String),
county LowCardinality(String)
)
ENGINE = MergeTree
ORDER BY (postcode1, postcode2, addr1, addr2);املأ الجدول مباشرةً من مصدر CSV عام:
INSERT INTO uk.uk_price_paid
SELECT
toUInt32(price_string) AS price,
parseDateTimeBestEffortUS(time) AS date,
splitByChar(' ', postcode)[1] AS postcode1,
splitByChar(' ', postcode)[2] AS postcode2,
transform(a, ['T', 'S', 'D', 'F', 'O'], ['terraced', 'semi-detached', 'detached', 'flat', 'other']) AS type,
b = 'Y' AS is_new,
transform(c, ['F', 'L', 'U'], ['freehold', 'leasehold', 'unknown']) AS duration,
addr1,
addr2,
street,
locality,
town,
district,
county
FROM url(
'http://prod1.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-complete.csv',
'CSV',
'uuid_string String,
price_string String,
time String,
postcode String,
a String,
b String,
c String,
addr1 String,
addr2 String,
street String,
locality String,
town String,
district String,
county String,
d String,
e String'
) SETTINGS max_http_get_redirects=10;30906560 rows in set. Elapsed: 59.852 sec. Processed 30.91 million rows, 5.41 GB (516.39 thousand rows/s., 90.40 MB/s.)
Peak memory usage: 485.15 MiB.كتابة البيانات في جدول Iceberg
إنشاء جدول Iceberg
للقراءة المباشرة من جدول Iceberg موجود، نوصي باستخدام دالة الجدول icebergS3. يوضّح هذا الدليل إنشاء جداول Iceberg مستقلة وتعبئتها، لذا يستخدم محرك الجدول IcebergS3 مع مخطط صريح. تحتوي مواقع S3 الواردة في المثال بالفعل على الجداول المكتملة؛ ولتشغيل عبارتي CREATE وINSERT، استبدل كلا الموقعين ببادئات S3 فارغة قابلة للكتابة وبيانات اعتماد تتحكم بها.
لاحظ أنه يجب تبسيط المخطط مقارنةً بجدول MergeTree المصدر. يدعم ClickHouse نظام أنواع أكثر ثراءً من Iceberg وملفات Parquet الأساسية، لذا فإن الأنواع مثل Enum وLowCardinality وUInt8 غير مدعومة في Iceberg ويجب تحويلها إلى أنواع متوافقة.
CREATE TABLE uk.uk_iceberg
(
price UInt32,
date Date,
postcode1 String,
postcode2 String,
type UInt32,
is_new UInt32,
duration UInt32,
addr1 String,
addr2 String,
street String,
locality String,
town String,
district String,
county String
)
ENGINE = IcebergS3('https://datasets-documentation.s3.amazonaws.com/lake_formats/iceberg_uk_price_paid/', '<aws_access_key>', '<aws_secret_key>', '<session_token>')إدراج مجموعة فرعية من البيانات
استخدم INSERT INTO SELECT لكتابة البيانات من جدول MergeTree إلى جدول Iceberg. في هذا المثال، نُدرِج معاملات لندن فقط:
يتطلب هذا المثال إعداد allow_insert_into_iceberg. راجع مصفوفة الدعم لمعرفة مستوى النضج والقيود الحالية.
SET allow_insert_into_iceberg = 1;
INSERT INTO uk.uk_iceberg SELECT *
FROM uk.uk_price_paid
WHERE town = 'LONDON'2346741 rows in set. Elapsed: 1.419 sec. Processed 30.91 million rows, 153.43 MB (21.78 million rows/s., 108.15 MB/s.)
Peak memory usage: 371.60 MiB.الاستعلام عن جدول Iceberg
تُخزَّن البيانات الآن بصيغة Iceberg في التخزين الكائني، ويمكن الاستعلام عنها عبر ClickHouse أو أي أداة أخرى تقرأ Iceberg:
SELECT
locality,
count()
FROM uk.uk_iceberg
WHERE locality != ''
GROUP BY locality
ORDER BY count() DESC
LIMIT 10┌─locality────┬─count()─┐
│ LONDON │ 896796 │
│ WALTHAMSTOW │ 8610 │
│ LEYTON │ 3525 │
│ CHINGFORD │ 3133 │
│ HORNSEY │ 2794 │
│ STREATHAM │ 2760 │
│ WOOD GREEN │ 2443 │
│ ACTON │ 2155 │
│ LEYTONSTONE │ 2102 │
│ EAST HAM │ 2085 │
└─────────────┴─────────┘
10 rows in set. Elapsed: 0.329 sec. Processed 457.86 thousand rows, 2.62 MB (1.39 million rows/s., 7.95 MB/s.)
Peak memory usage: 12.19 MiB.كتابة النتائج المجمّعة
لا تقتصر جداول Iceberg على تخزين الصفوف الخام، بل يمكنها أيضًا الاحتفاظ بمخرجات عمليات التجميع والتحويل، أي نتائج عمليات ETL التي تُنفَّذ داخل ClickHouse. ويفيد ذلك في نشر الملخصات المحسوبة مسبقًا إلى lakehouse لاستخدامها في المراحل اللاحقة.
أنشئ جدول Iceberg للبيانات المجمّعة
CREATE TABLE uk.uk_avg_town
(
price Float64,
town String
)
ENGINE = IcebergS3('https://datasets-documentation.s3.amazonaws.com/lake_formats/iceberg_uk_avg_town/', '<aws_access_key>', '<aws_secret_key>', '<session_token>')إدراج البيانات المُجمَّعة
احسب متوسط أسعار العقارات حسب البلدة، ثم اكتب النتائج مباشرةً في Iceberg:
INSERT INTO uk.uk_avg_town SELECT
avg(price) AS price,
town
FROM uk.uk_price_paid
GROUP BY town1173 rows in set. Elapsed: 0.480 sec. Processed 30.91 million rows, 185.44 MB (64.34 million rows/s., 386.05 MB/s.)
Peak memory usage: 4.18 MiB.الاستعلام عن الجدول المجمّع
يمكن الآن للأدوات الأخرى — ولمثيلات ClickHouse الأخرى — قراءة مجموعة البيانات المحسوبة مسبقًا:
SELECT
town,
price
FROM uk.uk_avg_town
ORDER BY price DESC
LIMIT 10┌─town───────────────┬──────────────price─┐
│ GATWICK │ 28232811.583333332 │
│ THORNHILL │ 985000 │
│ VIRGINIA WATER │ 984633.2938574939 │
│ CHALFONT ST GILES │ 863347.7280187573 │
│ COBHAM │ 775251.47313278 │
│ PURFLEET-ON-THAMES │ 772651.8 │
│ BEACONSFIELD │ 746052.9327405858 │
│ ESHER │ 686708.4969745865 │
│ KESTON │ 654541.1774842045 │
│ GERRARDS CROSS │ 639109.4084023251 │
└────────────────────┴────────────────────┘
10 rows in set. Elapsed: 0.210 sec.