المقدمة
عانت بحيرات البيانات التقليدية منذ فترة طويلة من مشكلة "مستنقع البيانات". بينما توفر قابلية التوسع والفعالية من حيث التكلفة للتخزين الكائني (مثل AWS S3 أو Azure Blob Storage)، فإنها غالباً ما تفتقر إلى الموثوقية والاتساق والأداء المتوقعين من قاعدة بيانات. هنا يأتي دور دلتا ليك (Delta Lake)، وهو طبقة تخزين مفتوحة المصدر تجلب الموثوقية والأداء إلى بحيرات البيانات. من خلال الجمع بين أفضل ميزات بحيرة البيانات وقدرات إدارة مستودع البيانات، يمكّن دلتا ليك من هندسة معمارية بحيرة البيانات (Data Lakehouse)، ليصبح المعيار لخطوط أنابيب هندسة البيانات الحديثة.
القدرات الأساسية لدلتا ليك
يوسع دلتا ليك قدرات ملفات باركيث (Parquet) من خلال توفير إدارة البيانات الوصفية فوق تنسيقات ملفات البيانات القياسية. وهو مبني على سجل معاملات يضمن سلامة البيانات. تشمل الميزات الأكثر أهمية لأي مهندس بيانات ما يلي:
- المعاملات ACID: يضمن اتساق البيانات حتى أثناء عمليات القراءة والكتابة المتزامنة. يمنع هذا القراءة الجزئية ويضمن أنه إذا فشلت عملية الكتابة، تظل مجموعة البيانات في حالتها الأصلية.
- فرض المخطط وتطوره (Schema Enforcement & Evolution): يمنع دلتا ليك البيانات غير الصالحة من الدخول إلى البحيرة من خلال فرض المخططات. كما يسمح بتطور المخطط، مما يتيح لك إضافة أعمدة جديدة أو تغيير الأنواع دون تعطيل خطوط الأنابيب الحالية.
- السفر عبر الزمن (الإصدار): يُعد هذا على الأرجح الميزة الأكثر قوة. يمكنك الوصول إلى الإصدارات السابقة من بياناتك عن طريق تحديد رقم إصدار أو طابع زمني، مما يتيح تصحيح الأخطاء بسهولة، والتدقيق، وقدرات التراجع.
- توحيد المعالجة الدفعية والتدفق: يوفر دلتا ليك واجهة برمجة تطبيقات (API) متسقة لكل من المعالجة الدفعية والتدفق، مما يبسط تعقيد الحفاظ على أنظمة منفصلة للبيانات التاريخية والبيانات في الوقت الفعلي.
تنفيذ دلتا ليك باستخدام PySpark
لاستغلال دلتا ليك، عادةً ما يتم استخدامه مع Apache Spark. فيما يلي مثال عملي يوضح كيفية إنشاء جدول دلتا، وإجراء عملية كتابة مع فرض المخطط، والاستفادة من السفر عبر الزمن للاستعلام عن الإصدارات السابقة.
from delta.tables import DeltaTable
from pyspark.sql import SparkSession
# تهيئة جلسة عمل Spark
spark = SparkSession.builder \
.appName("DeltaLakeExample") \
.config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
.config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \
.getOrCreate()
# 1. إنشاء جدول دلتا مع فرض المخطط
data = [
("1", "Alice", 30),
("2", "Bob", 25)
]
df = spark.createDataFrame(data, ["id", "name", "age"])
# حفظه كجدول دلتا. يقوم هذا تلقائياً بإنشاء سجل المعاملات.
delta_path = "/path/to/delta/table"
df.write.format("delta").mode("overwrite").save(delta_path)
# 2. السفر عبر الزمن: الاستعلام عن الإصدار 0
# يسترجع هذا البيانات كما كانت موجودة في الإصدار السابق
df_v0 = spark.read.format("delta").option("versionAsOf", 0).load(delta_path)
df_v0.show()
# 3. عملية الدمج (Upsert) - دمج
new_data = [
("1", "Alice", 31),
("3", "Charlie", 35)
]
df_new = spark.createDataFrame(new_data, ["id", "name", "age"])
# دمج البيانات الجديدة في الجدول الموجود
delta_table = DeltaTable.forPath(spark, delta_path)
delta_table.alias("old").merge(
df_new.alias("new"),
"old.id = new.id"
).whenMatchedUpdateAll() \
.whenNotMatchedInsertAll() \
.execute()
في الكود أعلاه، لاحظ استخدام option("versionAsOf", 0). يتيح لك هذا استعلام الحالة الدقيقة للبيانات قبل إجراء أي تعديلات. علاوة على ذلك، توضح دالة merge كيفية تبسيط دلتا ليك لعمليات الدمج (Upsert)، والتي كانت معروفة بصعوبتها وبطئها في بحيرات البيانات المعتمدة على باركيث القياسية.
تحسين الأداء: الأوامر Vacuum و Optimize
نظراً لأن دلتا ليك يحتفظ بسجل للتغيرات للسفر عبر الزمن والامتثال لـ ACID، فقد تتراكم الملفات الصغيرة مع مرور الوقت. للحفاظ على الأداء، هناك أمران أساسيان:
.optimize(): يقوم هذا الأمر بدمج الملفات الصغيرة في ملفات أكبر ومحسّنة، مما يسرع استعلامات القراءة بشكل كبير..vacuum(): يحذف هذا الأمر الملفات القديمة التي لم يعد سجل المعاملات يشير إليها. تحذير: تأكد من إعداد سياسة الاحتفاظ بشكل صحيح، حيث يؤدي الأمر vacuum إلى حذف البيانات التاريخية اللازمة للسفر عبر الزمن بشكل دائم بعد فترة الاحتفاظ المحددة.
الخاتمة
نجح دلتا ليك في سد الفجوة بين مرونة بحيرات البيانات وموثوقية مستودعات البيانات. بالنسبة لمهندسي البيانات، فإنه يوفر حلاً قوياً للمشاكل الشائعة مثل تلف البيانات، وانحراف المخطط، وبطء أداء الاستعلامات. من خلال دمج المعاملات ACID، والسفر عبر الزمن، والمعالجة الموحدة في إطار عمل مفتوح المصدر واحد، يوفر دلتا ليك الأساس لبناء معماريات بيانات قابلة للتوسع، وموثوقة، وعالية الأداء. سواء كنت تستخدم Databricks أو AWS EMR أو Azure Synapse، فإن إتقان دلتا ليك لم يعد خياراً بل أصبح ضرورة لهندسة البيانات الحديثة.