قواعد البيانات السحابية و NoSQL
أين تعيش قواعد البيانات اليوم، ومتى تحتاج نموذجًا غير الجداول. ⏱ نحو 45 دقيقة.
- تشرح فكرة قواعد البيانات المُدارة في السحابة وما يبقى مسؤوليتك.
- تميز أنواع
NoSQLومتى يناسب كل منها. - تخزن
JSONBوتستعلم عنه بـ->و ->> و @> وتفهرسه بـGIN. - تقابل مفاهيم
PostgreSQLبمفاهيمFirestore.
١قاعدة البيانات في السحابة
في أغلب المشاريع الحديثة لا تثبّت PostgreSQL على خادمك، بل تستأجر خدمة مُدارة: المزوّد يتولى التثبيت والتحديثات والنسخ الاحتياطي والتوسّع، وأنت تتصل وتكتب SQL كما تعلمت تمامًا.
| ما يتولاه المزوّد | ما يبقى عليك |
|---|---|
| تثبيت الخادم وتحديثه | تصميم الجداول والفهارس |
| النسخ الاحتياطي التلقائي | كتابة استعلامات وإجراءات جيدة |
| النسخ المتماثلة وتجاوز الأعطال | الصلاحيات والأمان |
| زيادة الموارد بضغطة | مراقبة البطء والكلفة |
أمثلة لخدمات PostgreSQL المُدارة: Amazon RDS و Aurora، و Google Cloud SQL و AlloyDB، و Azure Database for PostgreSQL، و Supabase و Neon. وخدمات مماثلة لـ Oracle و MySQL. كل ما تعلمته في هذا المقرر يعمل عليها.
٢NoSQL: نماذج أخرى للبيانات
| النوع | الفكرة | أمثلة | يناسب |
|---|---|---|---|
| المستندات Document | كل سجل وثيقة JSON مرنة البنية | MongoDB، Firestore | بيانات متغيرة البنية، تطبيقات الجوال |
مفتاح-قيمة Key-Value | قيمة تُجلب بمفتاحها فقط، بسرعة كبيرة | Redis، DynamoDB | الجلسات، والتخزين المؤقت |
| الأعمدة العريضة | صفوف ضخمة موزعة على خوادم كثيرة | Cassandra | سجلات بأحجام هائلة |
| الرسوم البيانية Graph | عقد وعلاقات | Neo4j | الشبكات الاجتماعية، والتوصيات |
| العلائقية SQL | NoSQL المستندات | |
|---|---|---|
| البنية | ثابتة بقيود | مرنة لكل وثيقة |
| العلاقات والربط | قوية (JOIN) | ضعيفة؛ تُكرر البيانات داخل الوثيقة |
| المعاملات | كاملة (ACID) | محدودة غالبًا |
| المناسب | المال، والطلبات، والمخزون | المحتوى المرن، والسرعة على نطاق واسع |
والواقع أن كثيرًا من الأنظمة تجمع الاثنين. و PostgreSQL نفسها تقدم أفضل ما في العالمين بنوع jsonb.
٣JSONB: وثائق مرنة داخل PostgreSQL
مواصفات المنتجات تختلف: للحاسب ذاكرة، وللشاشة حجم، وللكتاب صفحات. بدل عشرات الأعمدة الفارغة، نضع المواصفات في عمود jsonb:
ALTER TABLE products ADD COLUMN attrs jsonb;UPDATE products SET attrs = '{"brand": "نور", "color": "فضي", "ram_gb": 16, "ports": ["USB-C", "HDMI"]}' WHERE id = 1;UPDATE products SET attrs = '{"brand": "نور", "color": "أسود", "storage_gb": 128}' WHERE id = 2;UPDATE products SET attrs = '{"brand": "رؤية", "color": "أسود", "size_in": 27, "ports": ["HDMI", "DP"]}' WHERE id = 3;UPDATE products SET attrs = '{"brand": "نور", "color": "أبيض", "wireless": true}' WHERE id = 4;UPDATE products SET attrs = '{"pages": 320, "author": "فريق المتجر"}' WHERE id = 7; SELECT name, attrs ->> 'brand' AS الشركة, attrs ->> 'color' AS اللون, (attrs ->> 'ram_gb')::int AS الذاكرةFROM products WHERE attrs IS NOT NULL ORDER BY id;
| name | الشركة | اللون | الذاكرة |
|---|---|---|---|
| حاسب محمول | نور | فضي | 16 |
| جهاز لوحي | نور | أسود | NULL |
| شاشة 27 بوصة | رؤية | أسود | NULL |
| فأرة لاسلكية | نور | أبيض | NULL |
| تعلم SQL | NULL | NULL | NULL |
| العامل | المعنى | مثال |
|---|---|---|
-> | يُرجع الحقل كـ jsonb | attrs -> 'ports' |
->> | يُرجع الحقل كنص | attrs ->> 'color' |
@> | هل تحتوي الوثيقة على …؟ | attrs @> '{"color": "أسود"}' |
? | هل المفتاح موجود؟ | attrs ? 'wireless' |
ALTER TABLE products ADD COLUMN attrs jsonb;UPDATE products SET attrs = '{"brand": "نور", "color": "فضي", "ram_gb": 16, "ports": ["USB-C", "HDMI"]}' WHERE id = 1;UPDATE products SET attrs = '{"brand": "نور", "color": "أسود", "storage_gb": 128}' WHERE id = 2;UPDATE products SET attrs = '{"brand": "رؤية", "color": "أسود", "size_in": 27, "ports": ["HDMI", "DP"]}' WHERE id = 3;UPDATE products SET attrs = '{"brand": "نور", "color": "أبيض", "wireless": true}' WHERE id = 4;UPDATE products SET attrs = '{"pages": 320, "author": "فريق المتجر"}' WHERE id = 7;CREATE INDEX ix_products_attrs ON products USING gin (attrs); SELECT name FROM products WHERE attrs @> '{"brand": "نور", "color": "أسود"}';SELECT name FROM products WHERE attrs -> 'ports' ? 'HDMI';
| name |
|---|
| جهاز لوحي |
| name |
|---|
| حاسب محمول |
| شاشة 27 بوصة |
فهرس GIN يسرّع البحث بـ @> و ? داخل الوثائق على الجداول الكبيرة.
ويمكن بناء JSON من الجداول، كما يفعل الخادم قبل إرسال البيانات لتطبيق الجوال:
SELECT jsonb_build_object( 'customer', c.name, 'orders', jsonb_agg(jsonb_build_object('id', o.id, 'status', o.status) ORDER BY o.id) ) AS وثيقةFROM customers c JOIN orders o ON o.customer_id = c.idWHERE c.id = 1GROUP BY c.name;
| وثيقة |
|---|
| {"orders":[{"id":1,"status":"shipped"},{"id":3,"status":"paid"},{"id":11,"status":"new"}],"customer":"سارة"} |
٤المفهوم نفسه في Firestore
في قواعد المستندات مثل Firebase Firestore لا يوجد SQL؛ تُكتب الاستعلامات بدوال في لغة التطبيق. المفاهيم نفسها: مجموعة (≈ جدول)، ووثيقة (≈ صف)، وحقول (≈ أعمدة)، وفهارس. هذا للاطلاع فقط ولا يُشغَّل هنا:
// Firestore (JavaScript) — منتجات «نور» السوداءconst q = query( collection(db, "products"), where("attrs.brand", "==", "نور"), where("attrs.color", "==", "أسود"));const snap = await getDocs(q);snap.forEach(doc => console.log(doc.data().name));
| PostgreSQL | Firestore |
|---|---|
| جدول products | مجموعة collection "products" |
| صف | وثيقة document |
WHERE attrs @> '{"brand": "نور"}' | where("attrs.brand", "==", "نور") |
| JOIN | لا يوجد: تُكرر البيانات أو تُجلب بطلبات متعددة |
| إجراء مخزن أو محفز | Cloud Functions تعمل عند تغيّر الوثائق |
توقّع وتحقّق
ما الذي يتولاه مزوّد الخدمة المُدارة؟
أنسب نوع لتخزين جلسات المستخدمين مؤقتًا:
العامل الذي يُرجع حقل JSON كنص:
نوع الفهرس المناسب لـ jsonb:
الخلاصة
- الخدمة المُدارة تتولى التشغيل، والتصميم والاستعلامات مسؤوليتك.
- المستندات، ومفتاح-قيمة، والأعمدة العريضة، والرسوم البيانية: لكل نوع استخدامه.
jsonb: ->> نص، و ->jsonb، و @> احتواء، وGINللفهرسة.- الأعمدة المهمة الثابتة تبقى أعمدة عادية بقيود.
تحدٍّ برمجي: مواصفات مرنة للمنتجات
متوسطأضف إلى المنتجات عمود مواصفات jsonb، واملأه لمنتجين، وافهرسه، ثم ابحث فيه.
- عمود
specs jsonbفي products وفهرسGINعليه. - المنتج 5 (لوحة مفاتيح):
{"layout": "عربي", "wireless": false}، والمنتج 4 (فأرة):{"wireless": true, "dpi": 1600}. - آخر سطر: أسماء المنتجات اللاسلكية باستخدام
@>.
👀 اعرض الناتج المطلوب
| name |
|---|
| فأرة لاسلكية |
- الكود يعمل بلا أخطاء
- المنتجات اللاسلكية: فأرة لاسلكية
- مواصفات المنتج 4 صحيحة
- مواصفات المنتج 5 صحيحة
- فهرس GIN على specs
- البحث بـ @>
💡 تلميح 1
true لا "true".💡 تلميح 2
CREATE INDEX … ON products USING gin (specs);حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
ALTER TABLE products ADD COLUMN specs jsonb;UPDATE products SET specs = '{"layout": "عربي", "wireless": false}' WHERE id = 5;UPDATE products SET specs = '{"wireless": true, "dpi": 1600}' WHERE id = 4;CREATE INDEX ix_products_specs ON products USING gin (specs); SELECT name FROM products WHERE specs @> '{"wireless": true}';