لسنوات، كان بناء Lakehouse يعني تجميع نظام موزّع صغير: عنقود Spark، وخدمة كتالوج، وصيغة جداول، ومهمة ضغط (compaction) لتنظيف الفوضى التي تخلّفها هذه المكونات معًا. في 2026 انكسرت هذه الفرضية أخيرًا. إصداران متقاربان — DuckLake v1.0 في أبريل وDuckDB-Iceberg v1.5.3 بدعم كامل لـ Iceberg v3 في مايو — يعنيان أنك تستطيع اليوم تشغيل Lakehouse جدّي بضمانات ACID كاملة من محرك يعمل على جهاز واحد وتثبّته بأمر واحد.
في هذا الدليل نستعرض ما تغيّر، والفرق بين الصيغتين، وكيف تختار بينهما لمشروع حقيقي.
ما هو الـ Lakehouse من دون العنقود؟
يخزّن الـ Lakehouse البيانات كملفات مفتوحة (غالبًا Parquet) على تخزين الكائنات، مع إضافة ضمانات قواعد البيانات فوقها: معاملات ACID، وتطوير المخطط، والسفر عبر الزمن (time travel)، والكتابة المتزامنة. لم تكن البيانات نفسها هي المشكلة يومًا — فصيغة Parquet مستقرة منذ عقد. المشكلة هي البيانات الوصفية: معرفة أي الملفات تنتمي إلى أي نسخة من أي جدول، وتنسيق الكُتّاب المتزامنين حتى لا يفسد بعضهم عمل بعض.
حلّت Apache Iceberg المشكلة بملفات بيانات وصفية مخزنة بجانب البيانات، مع خدمة كتالوج تشير إلى النسخة الحالية. أما DuckLake، الذي أصدره فريق DuckDB، فيطرح سؤالًا أبسط: إذا كنت تحتاج قاعدة بيانات لتنسيق الكتالوج على أي حال، فلماذا لا تضع كل البيانات الوصفية في تلك القاعدة وتتخلى عن إدارة الملفات المتناثرة نهائيًا؟
DuckLake 1.0: البيانات الوصفية تسكن قاعدة بيانات
صدر DuckLake v1.0 في 13 أبريل 2026 كمواصفة جاهزة للإنتاج مع توافق رجعي مضمون. التطبيق المرجعي هو إضافة ducklake في DuckDB v1.5.2، وقد دخلت بالفعل قائمة أكثر عشر إضافات تنزيلًا في DuckDB.
الفكرة الجوهرية: ملفات البيانات هي Parquet عادي على تخزين الكائنات، بينما تعيش كل البيانات الوصفية — اللقطات (snapshots) والمخططات وقوائم الملفات والإحصاءات — كصفوف في قاعدة بيانات SQL تلعب دور الكتالوج. يمكن أن تكون هذه القاعدة SQLite لمشروع محلي، أو PostgreSQL لفريق متعدد الكُتّاب، أو DuckDB نفسه.
البداية تحتاج ثلاث عبارات فقط:
INSTALL ducklake;
ATTACH 'ducklake:postgres:dbname=lake_catalog host=db.internal'
AS lake (DATA_PATH 's3://my-bucket/lake/');
CREATE TABLE lake.orders (id INT, status VARCHAR, total DECIMAL(10,2));بعد ذلك يتصرف النظام كقاعدة بيانات عادية — إدراج وتحديث وحذف وربط بين الجداول، وكلها معاملات — بينما تستقر البيانات كملفات Parquet يستطيع أي طرف قراءتها.
تضمين البيانات ينهي مشكلة الملفات الصغيرة
الميزة الأبرز في v1.0 هي تضمين البيانات (data inlining)، وهي مفعّلة افتراضيًا الآن. عمليات الإدراج والتحديث والحذف الصغيرة تُخزَّن كصفوف في قاعدة الكتالوج بدل أن ينتج عن كل واحدة ملف Parquet ضئيل. ثم يأتي checkpoint لاحقًا فيدفعها إلى تخزين الكائنات دفعات معقولة:
CREATE TABLE lake.t (id INT, status VARCHAR);
INSERT INTO lake.t VALUES (1, 'en route'), (2, 'shipped');
DELETE FROM lake.t WHERE id = 1;
UPDATE lake.t SET status = 'delivered' WHERE id = 2;
FROM ducklake_list_files('lake', 't'); -- فارغة: لم يُكتب أي ملف بعد
CHECKPOINT; -- الآن تُدفع البيانات إلى Parquetهذه هي مشكلة «التغييرات الصغيرة» التي تعاني منها كل صيغ الجداول المبنية على الملفات، وقد حُلّت ببساطة لأن قاعدة بيانات باتت متاحة. وهذا أيضًا يجعل الإدخال المتدفق (streaming) إلى البحيرة عمليًا من دون خدمة ضغط.
جداول مرتّبة وتقسيم bucket وأنواع أغنى
يجلب الإصدار أيضًا الجداول المرتّبة (ALTER TABLE ... SET SORTED BY (id ASC)) لتقليم أفضل للملفات ومجموعات الصفوف، وتقسيمًا بالـ bucket يستخدم عمدًا دالة murmur3 لتوافق كامل مع Iceberg:
ALTER TABLE lake.events SET PARTITIONED BY (bucket(8, user_name));كما توسّع نظام الأنواع: نوع GEOMETRY مع دفع مرشحات الصناديق المحيطة إلى الأسفل، ونوع VARIANT للبيانات شبه المهيكلة — بترميز ثنائي قابل للتفكيك إلى أعمدة أولية، ويدعم التواريخ والطوابع الزمنية التي لا يستطيع JSON تمثيلها. يرى فريق DuckDB أن VARIANT سيحل محل JSON تدريجيًا كنوع افتراضي للبيانات شبه المهيكلة، وقد راهن مجتمع Iceberg على الرهان نفسه.
Iceberg v3: المواصفة تلحق بالركب
Apache Iceberg v3 هو أكبر مراجعة لصيغة الجداول المفتوحة المهيمنة منذ سنوات، و2026 هي سنة تحوّلها إلى واقع: إتاحة عامة على Snowflake منذ مايو وعلى Databricks Runtime 18، وبقية المنظومة تتبعهما. أبرز الميزات:
- متجهات الحذف الثنائية. بدل ملفات الحذف الموضعي في v2، يحصل كل ملف بيانات على خريطة بتات Roaring مضغوطة (تُخزَّن في ملفات Puffin) تعلّم الصفوف المحذوفة — قراءة أسرع بكثير في نمط merge-on-read وملفات صغيرة أقل بكثير.
- نوع VARIANT. النوع شبه المهيكل الثنائي نفسه الذي تبنّاه DuckLake، ومُعرَّف في مشروع Parquet، مع تفكيك صديق لدفع المرشحات.
- تتبّع نسب الصفوف. تتبّع على مستوى الصف لوقت إضافة الصفوف وتعديلها، بما يفتح الباب للمعالجة التزايدية وتدفقات التغييرات.
- قيم افتراضية للأعمدة وTIMESTAMP_NS. تطوير المخطط من دون إعادة كتابة الملفات، وطوابع زمنية بدقة النانوثانية.
إذا كنت تشغّل جداول Iceberg اليوم، فإن v3 هي الترقية التي تجعل التحديثات والحذف المتكرر ميسور التكلفة.
DuckDB عميلًا لـ Iceberg v3
الجزء الثاني من القصة أن DuckDB-Iceberg v1.5.3 حوّل DuckDB إلى عميل Iceberg حقيقي للقراءة والكتابة — بتنفيذ أصلي داخل الإضافة، من دون اعتماد على مكتبات Iceberg خارجية أو JVM. أمام أي كتالوج Iceberg REST (مثل Polaris أو Lakekeeper أو Amazon S3 Tables أو Glue) يدعم DuckDB الآن MERGE INTO، وتطوير المخطط عبر ALTER TABLE، وتحويلات التقسيم bucket وtruncate، وقراءة وكتابة Iceberg v3 كاملة:
ATTACH 'warehouse' AS my_datalake (TYPE iceberg, ...);
-- إنشاء جدول v3 بنوع VARIANT وطوابع زمنية نانوثانية
CREATE TABLE my_datalake.default.v3_table
WITH ('format-version' = 3) AS
FROM (VALUES
(1, {'kind': 'click', 'x': 10}::VARIANT, TIMESTAMP_NS '2026-05-20 12:00:00.123456789'),
(2, {'kind': 'view'}::VARIANT, TIMESTAMP_NS '2026-05-20 12:00:00.987654321')
) t (id, payload, event_time);
-- عمليات الحذف تُكتب كمتجهات حذف ثنائية مدمجة
DELETE FROM my_datalake.default.v3_table WHERE id = 1;
-- ترقية جدول قائم في مكانه
ALTER TABLE my_datalake.default.renamed_table SET ('format-version' = 3);تستحق MERGE INTO إشارة خاصة: فهي الطريقة الموصى بها للتعبير عن الإدراج-أو-التحديث (upsert) على جداول بلا مفاتيح أساسية — أي كل جداول الـ Lakehouse — وهي تعمل الآن من طرف إلى طرف على Iceberg من داخل DuckDB.
DuckLake أم Iceberg؟ كلاهما في الواقع
القرار العملي في 2026 أقل ثنائية مما يبدو:
- اختر DuckLake عندما يتحكم فريقك في المنظومة كاملة ويريد أبسط تشغيل ممكن: قاعدة Postgres واحدة ككتالوج (ربما نسخة PostgreSQL 18 التي تشغّلها أصلًا)، وParquet على أي تخزين كائنات، ولا خدمات إضافية. الكتابات الصغيرة المتدفقة، وإعدادات DuckDB متعددة المستخدمين، والبحيرات للقراءة فقط المقدَّمة عبر HTTPS بسيط — كلها تعمل مباشرة.
- اختر Iceberg عندما يكون اتساع المنظومة أولوية — فـ Snowflake وDatabricks وSpark وTrino وFlink كلها تتحدثه — أو عندما تكون الجداول قائمة أصلًا وتعتمد عليها فرق أخرى.
- التوافق البيني مصمَّم من البداية. يخزّن DuckLake بياناته بصيغة Parquet مع تجزئة buckets متوافقة مع Iceberg ومتجهات حذف Puffin. وتنفّذ الدالة
iceberg_to_ducklakeترحيلًا للبيانات الوصفية فقط لكتالوج Iceberg كامل إلى DuckLake — من دون نسخ أي ملف بيانات — والنسخ من DuckLake إلى Iceberg مدعوم أيضًا.
نمط نوصي به أكثر فأكثر: DuckLake طبقةً تشغيلية سريعة يملكها فريق واحد، تنشر جداول منقّحة إلى Iceberg حيث تستهلكها بقية المؤسسة.
لماذا يهم هذا الفرق الصغيرة؟
بالنسبة للشركات الناشئة والمتوسطة في تونس والخليج وغيرهما، كان العائق التاريخي أمام معمارية الـ Lakehouse هو الكلفة التشغيلية: عناقيد تحتاج رعاية وخدمات كتالوج تحتاج تأمينًا، لأحجام بيانات نادرًا ما تبررها. هذا العذر انتهى. عملية DuckDB واحدة، وكتالوج Postgres، ودلو متوافق مع S3 تمنحك اليوم جداول ACID وسفرًا عبر الزمن وصيغًا مفتوحة — والمواصفة تستوعب صراحة تيراباتات من البيانات وملايين اللقطات. إذا كنت تبني استراتيجية بيانات مؤسسية للذكاء الاصطناعي، فهذه المنظومة هي أرخص أساس موثوق استطعنا التوصية به يومًا.
تخطط لمنصة بيانات، أو لترحيل تحليلاتك من الجداول الممتدة إلى Lakehouse؟ تحدّث إلى فريق نقطة — نصمم ونبني بنى تحتية للبيانات لفرق العمل في منطقة الشرق الأوسط وشمال أفريقيا.