تصميم قواعد البيانات وإتقان SQL
NoSQL: متى تختار ماذا
ليست كل مشكلة تُحل بأفضل طريقة باستخدام قاعدة بيانات علائقية. يغطي هذا الدرس الفئات الأربع الرئيسية لـ NoSQL ومتى يكون كل منها الخيار الصحيح ونظرية CAP عمليًا وهياكل بيانات Redis التي يحب المحاورون السؤال عنها.
مخازن المستندات: MongoDB
قواعد بيانات المستندات تخزن البيانات كمستندات مرنة شبيهة بـ JSON (بصيغة BSON في MongoDB). كل مستند يمكن أن يكون بهيكل مختلف، وهذا مفيد عندما تتطور متطلبات المخطط بشكل متكرر.
التضمين مقابل المرجعية
قرار التصميم الأساسي في MongoDB هو ما إذا كنت ستُضمّن البيانات المرتبطة داخل المستند أو ستُشير إليها بمعرف.
{
"_id": "order_123",
"customer_name": "Alice Chen",
"items": [
{ "product": "Wireless Mouse", "price": 29.99, "qty": 2 },
{ "product": "USB-C Hub", "price": 49.99, "qty": 1 }
],
"total": 109.97,
"created_at": "2026-01-15T10:30:00Z"
}
| الاستراتيجية | متى تُستخدم | المقايضة |
|---|---|---|
| التضمين | البيانات تُقرأ معًا، الفرع ليس له وجود مستقل | قراءات أسرع، حد حجم المستند (16MB) |
| المرجعية | البيانات مشتركة بين المستندات، علاقات عدة-لعدة | تتطلب استعلامات متعددة، أكثر مرونة |
أفضل حالات الاستخدام لـ MongoDB:
- أنظمة إدارة المحتوى (مقالات بميتاداتا متنوعة)
- كتالوجات المنتجات بسمات غير متجانسة
- ملفات المستخدمين بحقول مرنة
- تسجيل الأحداث بمخططات أحداث متنوعة
مخازن المفتاح-القيمة: Redis وDynamoDB
مخازن المفتاح-القيمة تربط مفتاحًا فريدًا بقيمة. تقدم أسرع أداء قراءة/كتابة لكن مع قدرات استعلام محدودة.
هياكل بيانات Redis
Redis أكثر بكثير من مجرد ذاكرة مؤقتة بسيطة للمفتاح-القيمة. هياكل بياناتها الغنية تجعلها أداة قوية لأنماط محددة يسأل عنها المحاورون بشكل متكرر.
المجموعات المرتبة (Sorted Sets) -- لوحات المتصدرين:
# إضافة نقاط اللاعبين إلى لوحة المتصدرين
ZADD leaderboard 1500 "player:alice"
ZADD leaderboard 2200 "player:bob"
ZADD leaderboard 1800 "player:charlie"
# أفضل 3 لاعبين مع النقاط (الأعلى أولاً)
ZREVRANGE leaderboard 0 2 WITHSCORES
# النتيجة: ["player:bob", "2200", "player:charlie", "1800", "player:alice", "1500"]
# ترتيب اللاعب (يبدأ من 0، أعلى نقاط = ترتيب 0)
ZREVRANK leaderboard "player:alice"
# النتيجة: 2
HyperLogLog -- العد الفريد:
# عد الزوار الفريدين (يستخدم ~12KB بغض النظر عن العدد)
PFADD daily_visitors:2026-01-15 "user:101" "user:102" "user:103"
PFADD daily_visitors:2026-01-15 "user:101" # مكرر، لا يُحسب
PFCOUNT daily_visitors:2026-01-15
# النتيجة: 3 (تقريبي، خطأ معياري 0.81%)
# دمج عدة أيام للعد الأسبوعي
PFMERGE weekly_visitors daily_visitors:2026-01-15 daily_visitors:2026-01-16
Pub/Sub -- المراسلة الفورية:
# المشترك يستمع على قناة
SUBSCRIBE chat:room:42
# الناشر يرسل رسالة
PUBLISH chat:room:42 "Hello everyone!"
DynamoDB: تصميم مفتاح التقسيم
DynamoDB (من AWS) هو مخزن مفتاح-قيمة ومستندات مُدار مصمم للتوسع الهائل. مفتاح التقسيم يحدد كيفية توزيع البيانات عبر الأقسام.
مفتاح تقسيم جيد: تعدد عالٍ، توزيع متساوٍ (مثل user_id، order_id)
مفتاح تقسيم سيئ: تعدد منخفض، أقسام ساخنة (مثل status، country -- معظم الكتابات تذهب لقيم قليلة)
{
"PK": "USER#alice123",
"SK": "ORDER#2026-01-15#order_789",
"total": 109.97,
"status": "shipped"
}
نمط تصميم الجدول الواحد في DynamoDB يستخدم مفتاحًا أساسيًا مركبًا (مفتاح تقسيم + مفتاح فرز) لتخزين أنواع كيانات متعددة في جدول واحد، مما يتيح أنماط وصول فعالة باستعلام واحد.
مخازن عائلة الأعمدة: Cassandra
Apache Cassandra مصمم لأحمال الكتابة الثقيلة عبر مراكز بيانات متعددة. البيانات تُنظم حسب مفتاح التقسيم ومفتاح التجميع.
مفتاح التقسيم يحدد أي عقدة تخزن البيانات. مفتاح التجميع يحدد ترتيب الفرز داخل القسم.
CREATE TABLE sensor_readings (
sensor_id UUID,
reading_time TIMESTAMP,
temperature DOUBLE,
humidity DOUBLE,
PRIMARY KEY (sensor_id, reading_time)
) WITH CLUSTERING ORDER BY (reading_time DESC);
أفضل حالات الاستخدام لـ Cassandra:
- بيانات السلاسل الزمنية (مستشعرات IoT، المقاييس، السجلات)
- أحمال العمل كثيفة الكتابة (تتبع الأحداث، المراسلة)
- النشر متعدد المناطق الذي يحتاج كتابات منخفضة الكمون
- البيانات المقسمة طبيعيًا (لكل مستخدم، لكل جهاز)
قاعدة تصميم أساسية: في Cassandra، تصمم الجداول حول أنماط استعلامك، وليس حول الكيانات. كل نمط استعلام عادة يحصل على جدوله الخاص.
قواعد البيانات الرسومية: Neo4j
قواعد البيانات الرسومية تنمذج البيانات كعقد (كيانات) وحواف (علاقات). تتفوق عندما تكون العلاقات هي محور استعلاماتك الأساسي.
(:Person {name: "Alice"})-[:FOLLOWS]->(:Person {name: "Bob"})
(:Person {name: "Alice"})-[:PURCHASED]->(:Product {name: "Wireless Mouse"})
أفضل حالات الاستخدام:
- الشبكات الاجتماعية (أصدقاء الأصدقاء، الاتصالات المشتركة)
- محركات التوصيات (الأشخاص الذين اشتروا X اشتروا أيضًا Y)
- كشف الاحتيال (التحويلات المالية الدائرية)
- رسوم المعرفة (علاقات الكيانات)
متى لا تستخدم قاعدة بيانات رسومية: عمليات CRUD البسيطة، بيانات السلاسل الزمنية، أو عندما لا تكون العلاقات بين الكيانات مركزية لأنماط استعلامك.
مصفوفة قرار SQL مقابل NoSQL
| المعيار | اختر SQL | اختر NoSQL |
|---|---|---|
| هيكل البيانات | محدد جيدًا، علائقي | مرن، متطور |
| احتياجات الاتساق | اتساق قوي مطلوب (الخدمات المصرفية) | الاتساق النهائي مقبول |
| أنماط الاستعلام | عمليات ربط معقدة، تجميعات، استعلامات مخصصة | أنماط وصول معروفة، بحث بالمفتاح |
| نموذج التوسع | التوسع الرأسي كافٍ | التوسع الأفقي مطلوب |
| احتياجات المعاملات | معاملات ACID متعددة الصفوف | اتساق على مستوى مستند واحد أو نهائي |
| خبرة الفريق | مهارات SQL قوية | خبرة بنظام NoSQL محدد |
| نسبة القراءة/الكتابة | متوازنة أو كثيفة الكتابة مع قراءات معقدة | كثيفة القراءة بأنماط بسيطة |
نصيحة للمقابلة: لا تقل أبدًا "NoSQL أفضل من SQL" أو العكس. صِغ إجابتك دائمًا كالتالي: "لنمط الوصول هذا ومتطلب الاتساق هذا، سأختار X لأن..." أفضل إجابة تُظهر أنك تفهم المقايضات، وليس أن لديك مفضلاً.
نظرية CAP عمليًا
تنص نظرية CAP على أن النظام الموزع لا يمكنه ضمان سوى خاصيتين من ثلاث في وقت واحد:
- الاتساق (C): كل قراءة تُرجع أحدث كتابة
- التوفر (A): كل طلب يتلقى استجابة (ليس خطأ)
- تحمل التقسيم (P): النظام يستمر في العمل رغم انقسامات الشبكة
بما أن انقسامات الشبكة لا مفر منها في الأنظمة الموزعة، الاختيار الحقيقي هو بين CP (الاتساق أثناء الانقسام) وAP (التوفر أثناء الانقسام).
| قاعدة البيانات | تصنيف CAP | السلوك أثناء الانقسام |
|---|---|---|
| PostgreSQL (عقدة واحدة) | CA (غير موزع) | لا يتحمل التقسيم |
| Google Spanner | CP | يرفض الكتابات إذا لم يتوفر النصاب |
| MongoDB (الإعداد الافتراضي) | CP | انتخاب أساسي، عدم توفر مؤقت |
| DynamoDB | AP | يُرجع بيانات قد تكون قديمة، يحل لاحقًا |
| Cassandra | AP (قابل للضبط) | يقبل الكتابات، يحل التعارضات عبر آخر كتابة تفوز |
أنماط الاتساق النهائي
عند استخدام أنظمة AP، هذه الأنماط تساعد في إدارة الاتساق:
اقرأ كتاباتك (Read-your-writes): بعد أن يكتب المستخدم بيانات، قراءاته اللاحقة مضمونة لرؤية تلك الكتابة (حتى لو لم يرها المستخدمون الآخرون بعد). يُنفذ بتوجيه القراءات إلى نفس العقدة التي تعاملت مع الكتابة، أو بتضمين رمز إصدار.
القراءات الرتيبة (Monotonic reads): المستخدم لن يرى بيانات أقدم بعد أن رأى بيانات أحدث. يُنفذ بتثبيت قراءات المستخدم إلى نسخة متماثلة متسقة.
البادئة المتسقة (Consistent prefix): إذا حدثت الكتابة A قبل الكتابة B، أي قارئ يرى B سيرى أيضًا A. يُنفذ بترتيب الكتابات عبر قسم واحد أو باستخدام ساعات المتجهات.
نصيحة للمقابلة: عند مناقشة CAP، كن دقيقًا. قول "MongoDB هي CP" بدون سياق غير مكتمل. قل: "MongoDB بإعداد ضمان الكتابة وتفضيل القراءة الافتراضيين تتصرف كـ CP -- أثناء انتخاب أساسي، الكتابات غير متوفرة مؤقتًا. لكن مع تفضيل قراءة
secondaryPreferredوضمان كتابةw:1، يمكن أن تتصرف أكثر كـ AP، بقبول قراءات من نسخ ثانوية قد تكون قديمة." هذا المستوى من الدقة يُظهر فهمًا عميقًا.
تهانينا -- لقد أكملت وحدة تصميم قواعد البيانات وإتقان SQL. اختبر معرفتك مع اختبار الوحدة. :::