تعرّف على Amazon DynamoDB: نموذج NoSQL الخاص به، كيف تصمم المفاتيح والفهارس لأنماط الوصول، أوضاع السعة، Streams للمعالجات المعتمدة على الأحداث، ونصائح عملية لأنظمة منخفضة زمن الاستجابة وقابلة للتوسع.

Amazon DynamoDB هي خدمة قاعدة بيانات NoSQL مُدارة بالكامل من AWS، مصمَّمة للتطبيقات التي تحتاج إلى قراءات وكتابات بزمن استجابة منخفض وثابت عند أي مستوى تقريبًا من الحمل. «مُدارة بالكامل» تعني أن AWS تتولى العمل البنيوي — تزويد الأجهزة، التكرار، تصحيح الثغرات، والعديد من مهام التشغيل — بحيث يمكن للفرق التركيز على إطلاق الميزات بدلاً من تشغيل خوادم قواعد البيانات.
في جوهرها، تخزن DynamoDB البيانات كـ عناصر (صفوف) داخل جداول، لكن لكل عنصر سمات مرنة. يمكن فهم نموذج البيانات كمزيج من:
تختار الفرق DynamoDB عندما يريدون أداء متوقعًا وعمليات أبسط للحِملات التي لا تتناسب بسهولة مع الربط العلائقي. يُستخدم غالبًا للخدمات المصغرة (كل خدمة تمتلك بياناتها)، التطبيقات الخالية من الخوادم ذات حركة متقلبة، والأنظمة المعتمدة على الأحداث التي تتفاعل مع تغيُّر البيانات.
تستعرض هذه المقالة اللبنات الأساسية (الجداول، المفاتيح، والفهارس)، كيفية النمذجة حول أنماط الوصول (بما في ذلك تصميم الجدول الواحد)، كيفية عمل السعة وأنماط التدرج، ونماذج عملية لبث التغييرات إلى عمارة معتمدة على الأحداث.
تنظم DynamoDB حول عدد قليل من اللبنات البسيطة، لكن التفاصيل مهمة لأنها تحدد كيفية نمذجة البيانات ومدى سرعة (وتكلفة) الطلبات.
الجدول هو الحاوية العليا. كل سجل في الجدول هو عنصر (مشابه للصف)، وكل عنصر هو مجموعة من السمات (مشابهة للأعمدة).
على عكس قواعد البيانات العلائقية، لا تحتاج العناصر في نفس الجدول إلى مشاركة نفس السمات. قد يحتوي عنصر على {status, total, customerId} بينما يتضمن آخر {status, shipmentTracking} — لا تطلب DynamoDB مخططًا ثابتًا.
يُعرَّف كل عنصر بواسطة مفتاح أساسي، وتدعم DynamoDB نوعين:
في الممارسة، تُمكّن المفاتيح المركبة أنماط «مجمعة» مثل "كل الطلبات لعميل ما، الأحدث أولًا".
Query يقرأ عناصر حسب المفتاح الأساسي (أو مفتاح الفهرس). يستهدف مفتاح تقسيم محددًا ويمكن أن يفلتر حسب نطاقات مفتاح الفرز — هذا المسار الفعّال والمفضّل.
Scan يمسح الجدول كله (أو الفهرس) ثم يفلتر. سهل البدء به، لكنه عادة أبطأ وأكثر تكلفة على نطاق واسع.
بعض القيود التي ستشعر بها مبكرًا:
هذه الأساسيات تمهد لباقي الموضوع: أنماط الوصول، اختيارات الفهرسة، وخصائص الأداء.
توصف DynamoDB غالبًا كمخزن مفتاح-قيمة وقاعدة بيانات مستندات. هذا دقيق، لكن من المفيد فهم ما يعنيه كل جانب في التصميم اليومي.
في جوهرها، تسترجع البيانات بالمفتاح. قدّم قيم المفتاح الأساسي وتُرجع DynamoDB عنصرًا واحدًا. ذلك lookup بالمفتاح هو ما يوفر تخزينًا بزمن استجابة منخفض ومتنبأ للعديد من الأحمال.
وفي نفس الوقت، يمكن أن يحتوي العنصر على سمات متداخلة (خرائط وقوائم)، مما يجعله شبيهًا بقاعدة مستندات: يمكنك تخزين حمولات مُهيكلة دون تعريف مخطط صارم مسبقًا.
تتناسب العناصر طبيعيًا مع بيانات شبيهة بـ JSON:
profile.name, profile.address).هذا مناسب عندما يُقرأ الكيان عادةً ككل — مثل ملف المستخدم، سلة التسوق، أو حزمة إعدادات.
DynamoDB لا يدعم عمليات الربط (joins) على الخادم. إذا كان تطبيقك يحتاج إلى جلب "طلب مع عناصر سطره وحالة الشحن" في مسار قراءة واحد، فستقوم غالبًا بتكرار البيانات: نسخ بعض السمات في عناصر متعددة، أو تضمين هياكل فرعية صغيرة بداخل العنصر.
التكرار يزيد تعقيد الكتابة وقد يسبب تفجير التحديثات. المقابل هو عدد أقل من الرحلات ذهابًا وإيابًا وقراءات أسرع — وغالبًا ما يكون ذلك حاسمًا في أنظمة قابلة للتوسع.
أسرع استعلامات DynamoDB هي التي يمكنك التعبير عنها كـ “أعطني هذا التقسيم” (وبشكل اختياري “ضمن هذا التقسيم أعطني هذا النطاق”). لذلك اختيار المفتاح يتعلق في المقام الأول بكيفية قراءة البيانات، وليس فقط بكيفية تخزينها.
يحدد مفتاح التقسيم أي جزء مادي يخزن العنصر. تقوم DynamoDB بتجزئة هذه القيمة لتوزيع البيانات والحركة. إذا تركزت العديد من الطلبات على مجموعة صغيرة من قيم مفتاح التقسيم، يمكنك خلق "شرائح ساخنة" وضرب حدود السعة حتى لو كان الجدول في معظم الوقت خاملاً.
المفاتيح الجيدة:\n
"GLOBAL")مع مفتاح الفرز، تُخزَّن العناصر التي تشترك في نفس مفتاح التقسيم معًا وتُرتَّب حسب مفتاح الفرز. هذا يتيح:
BETWEEN, begins_with)نمط شائع هو تركيب مفتاح الفرز، مثل TYPE#id أو TS#2025-12-22T10:00:00Z، لدعم أشكال استعلام متعددة دون الحاجة لجداول إضافية.
PK = USER#<id> (عملية بسيطة)إذا كان مفتاح التقسيم يتوافق مع أعلى استعلاماتك من حيث الحجم ويُوزع بالتساوي، ستحصل على قراءات وكتابات بزمن استجابة منخفض ومتسق. إذا لم يكن كذلك، ستضطر للتعويض بمسوح، مرشحات، أو فهارس إضافية — كل منها يزيد التكلفة ويزيد خطر المفاتيح الساخنة.
تمنح الفهارس الثانوية لـ DynamoDB مسارات استعلام بديلة بخلاف مفتاح الجدول الأساسي. بدلاً من إعادة تشكيل الجدول الأساسي في كل مرة يظهر فيها نمط وصول جديد، يمكنك إضافة فهرس يعيد مفاتيح عناصرك لنمط استعلام مختلف.
الفهرس الثانوي العالمي (GSI) لديه مفتاح تقسيم خاص به (ومفتاح فرز اختياري) يمكن أن يختلف تمامًا عن جدول الأساس. إنه "عالمي" لكونه يغطي جميع أجزاء الجدول ويمكن إضافته أو إزالته في أي وقت. استخدم GSI عندما تحتاج مسار وصول جديد لا يتناسب مع تصميم المفتاح الأصلي — مثل استعلام الطلبات بحسب customerId بينما الجدول المفهرس حسب orderId.
الفهرس الثانوي المحلي (LSI) يشارك نفس مفتاح التقسيم مع الجدول الأساسي لكنه يستخدم مفتاح فرز مختلف. يجب تعريف LSIs عند إنشاء الجدول. تنفع عندما تريد أوامر فرز متعددة داخل نفس مجموعة الكيان (نفس مفتاح التقسيم)، مثل جلب طلبات العميل مرتبة حسب createdAt مقابل status.
الإسقاط يحدد أي السمات تُخزَّن في الفهرس:
كل كتابة إلى الجدول الأساسي قد تُثير كتابة إلى فهارس متعددة. المزيد من GSIs مع إسقاطات واسعة يزيد تكلفة الكتابة واستهلاك السعة. خطط للفهارس حول أنماط الوصول المستقرة وقلل السمات المُسقطة حينما تستطيع.
يبدأ تدرج DynamoDB بخيار: عند الطلب (On-Demand) أو مزود (Provisioned). كلاهما يمكن أن يصل إلى سعات عالية جدًا، لكنهما يتصرّفان بشكل مختلف عند تغيّر الحركة.
عند الطلب هو الأبسط: تدفع لكل طلب وتتكيف DynamoDB تلقائيًا مع الحمل المتغير. مناسب للحركة غير المتوقعة، المنتجات في مراحل مبكرة، والأحمال المتقلبة حيث لا تريد إدارة أهداف السعة.
مزود يعني تخطيط السعة: تحدد (أو تستخدم موازنة تلقائية) معدل قراءة وكتابة محددًا وتحصل على تسعير أكثر توقعًا عند استخدام ثابت. غالبًا ما يكون أرخص للأحمال المعروفة والمستمرة وللفِرق القادرة على توقع الطلب.
تقاس السعة المُزودة بـ:
حجم العنصر ونمط الوصول والتناسق يؤثرون على التكلفة الحقيقية: العناصر الأكبر، التناسق القوي، والمسوح يمكن أن تستهلك السعة بسرعة.
تعدِّل الموازنة التلقائية RCUs/WCUs المزودة استنادًا إلى أهداف الاستخدام. تساعد في النمو التدريجي والدورات المتوقعة، لكنها ليست فورية. الارتفاعات المفاجئة قد تُقيّد إذا لم تتدرج السعة سريعًا بما يكفي، ولا يمكنها إصلاح مفتاح تقسيم ساخن يُركّز الحركة على شارد واحد.
DynamoDB Accelerator (DAX) هو ذاكرة تخزين مؤقت في الذاكرة تقلل زمن قراءة وتخفف الطلبات المكررة (مثل صفحات المنتج الشعبية، عمليات البحث عن الجلسات، لوحات المتصدرين). مفيد عندما يطلب العديد من العملاء نفس العناصر مرارًا؛ لا يساعد في أنماط الكتابة الكثيفة ولا يغني عن تصميم مفاتيح سليم.
تسمح لك DynamoDB بالمفاضلة بين ضمانات القراءة وزمن الاستجابة والتكلفة، لذا من المهم تحديد ماذا يعني «الصحيح» لكل عملية.
افتراضيًا، GetItem و Query يستخدمان قراءات متسقة نهائيًا: قد ترى قيمة قديمة بعد الكتابة مباشرةً. هذا غالبًا ما يكون مقبولًا في خلاصات الأخبار، كتالوجات المنتجات، وواجهات القراءة الكثيفة الأخرى.
باستخدام القراءات المتسقة بقوة (خيار للقراءات من الجدول الأساسي في نفس المنطقة)، تضمن رؤية أحدث كتابة مؤكدة. التناسق القوي يكلف وحدات قراءة أكثر وقد يزيد الذيل الزمني، فاحتفظ به للقراءات الحرجة فعلاً.
التناسق القوي ذو قيمة للقراءات التي تؤدي إجراءات لا رجعة فيها:
بالنسبة للعدادات، النهج الأكثر أمانًا عادةً ليس «قراءة قوية ثم كتابة»، بل تحديث ذري (مثل UpdateItem مع ADD) حتى لا تضيع الزيادات.
توفر معاملات DynamoDB (TransactWriteItems, TransactGetItems) سمات ACID عبر ما يصل إلى 25 عنصرًا. مفيدة عندما يجب تحديث عناصر متعددة معًا — مثل كتابة طلب وحجز مخزون — أو فرض ثوابت لا تحتمل حالات وسيطة.
إعادة المحاولات طبيعية في الأنظمة الموزعة. اجعل الكتابات قابلة لإعادة التشغيل بأمان حتى لا تُضاعف التأثيرات:
ConditionExpression (مثال: "إنشئ فقط إذا لم يكن السمة موجودة")الصحة المنطقية في DynamoDB تتعلق أساسًا باختيار مستوى التناسق المناسب وتصميم العمليات بحيث لا تكسر إعادة المحاولات البيانات.
تخزن DynamoDB بيانات الجدول عبر عدة شرائح مادية. لكل شريحة سعة محدودة للقراءات والكتابات، بالإضافة إلى حد على كمية البيانات التي يمكن أن تحتويها. يحدد مفتاح التقسيم أين يعيش العنصر؛ إذا استهدفت الكثير من الطلبات نفس قيمة مفتاح التقسيم (أو مجموعة صغيرة من القيم)، تصبح تلك الشريحة عنق زجاجة.
المفاتيح الساخنة عادة ما تنجم عن اختيارات مفاتيح تجمع الحركة: مفتاح تقسيم "عام" مثل USER#1, TENANT#default, أو STATUS#OPEN، أو أنماط مرتبة زمنيًا حيث يكتب الجميع على "الآن" تحت مفتاح واحد.
ستلاحظ عادة:
ProvisionedThroughputExceededException) لمجموعة فرعية من المفاتيحصمّم من أجل التوزيع أولًا، ثم سهولة الاستعلام:
TENANT#<id> بدلاً من ثابت مشترك)ORDER#<id>#<shard> لنشر الكتابات عبر N شظايا، ثم استعلم عبر الشظايا عند الحاجةMETRIC#2025-12-22T10) لمنع "كل الكتابات تذهب إلى العنصر الأخير"للقمم غير المتوقعة، يمكن لسعة عند الطلب امتصاص الاندفاعات (ضمن حدود الخدمة). مع السعة المزودة، استخدم الموازنة التلقائية وطبّق ارتداد أُسِّي مع jitter على العملاء عند التقييد لتجنب إعادة المحاولات المتزامنة التي تضخم الذروة.
يبدأ نمذجة البيانات في DynamoDB من أنماط الوصول، وليس من مخططات الكيانات. تصمم المفتاح بحيث تصبح الاستعلامات المطلوبة عمليات Query سريعة، بينما يتم تجنب الباقي أو التعامل معه بشكل غير متزامن.
"تصميم الجدول الواحد" يعني تخزين أنواع كيانات متعددة (مستخدمون، طلبات، رسائل) في جدول واحد واستخدام اتفاقيات مفاتيح متسقة لجلب البيانات ذات الصلة في Query واحد. هذا يقلل الرحلات العابرة للكيانات ويجعل زمن الاستجابة متوقعًا.
نهج شائع هو المفاتيح المركبة:
PK يجمع قسمًا منطقيًا (مثال: USER#123)SK يرتب العناصر داخل تلك المجموعة (مثال: PROFILE, ORDER#2025-12-01, MSG#000123)هذا يتيح جلب "كل شيء لمستخدم" أو "الطلبات فقط لمستخدم" باختيار بادئة مفتاح الفرز.
للعلاقات الشبيهة بالرسم البياني، تعمل قائمة الجوار جيدًا: خزّن الحواف كعناصر.
PK = USER#123, SK = FOLLOWS#USER#456لدعم عمليات البحث العكسية أو many-to-many الحقيقية، أضف عنصر حافة معكوس أو اسقِط إلى GSI، اعتمادًا على مسارات القراءة.
لأحداث وقياسات، تجنّب التقسيم غير المحدود عبر التجميع:
PK = DEVICE#9#2025-12-22 (جهاز + يوم)SK = TS#1734825600 (طابع زمني)استخدم TTL لحذف النقاط القديمة تلقائيًا، واحتفظ بتجميعات (تجميعات ساعية/يومية) كعناصر منفصلة للواجهات السريعة.
إذا أردت مرجعًا أعمق حول اتفاقيات المفاتيح، راجع /blog/partition-key-and-sort-key-design.
DynamoDB Streams هو تغذية التغيرات المدمجة في DynamoDB. عند تمكينها على جدول، ينتج كل إدراج أو تحديث أو حذف سجل تيار يمكن للمُستهلِكين التعامل معه — دون الاستطلاع المستمر للجدول.
سجل التيار يحتوي على المفاتيح وربما الصورة القديمة والجديدة للعنصر، حسب نوع عرض التيار الذي تختاره (المفاتيح فقط، الصورة الجديدة، الصورة القديمة، أو كلاهما). تُجمّع السجلات في شُرَبة (shards) تُقرأ ترتيبيًا.
إعداد شائع هو DynamoDB Streams → AWS Lambda، حيث تحفز كل دفعة من السجلات دالة. يمكن أيضًا وجود مُستهلِكين مخصصين أو توصيل للأنظمة التحليلية/التسجيل.
أمثلة نموذجية:
هذا يحافظ على الجدول الأساسي مُحَسَّنًا للقراءات/الكتابات منخفضة الزمن ويُرحِّل العمل المشتق إلى معالِجات غير متزامنة.
توفر التيارات معالجة مُرتبة لكل شارد (التي عادة ما ترتبط بمفتاح التقسيم)، لكن لا يوجد ترتيب عالمي عبر كل المفاتيح. التسليم هو على الأقل مرة واحدة، لذا قد تحدث تكرارات.
للتعامل مع ذلك بأمان:
بتصميم يناسب هذه الضمانات، يمكن أن تحوّل Streams DynamoDB إلى قاعدة متينة لبُنى معتمدة على الأحداث.
DynamoDB مصممة لتوافر عالٍ عبر توزيع البيانات على مناطق التوفر داخل المنطقة. بالنسبة لمعظم الفرق، المكاسب العملية للموثوقية تأتي من وجود استراتيجية نسخ احتياطية واضحة، وفهم خيارات التكرار، ومراقبة المقاييس المناسبة.
النسخ الاحتياطية عند الطلب هي لقطات يدوية (أو مؤتمتة) تأخذها عندما تريد نقطة استعادة معروفة — قبل ترحيل، بعد إصدار، أو قبل عملية ملء كبيرة. رائعة للحظات "وضع إشارة".
الاستعادة إلى نقطة زمنية (PITR) تلتقط التغييرات باستمرار حتى تتمكن من استعادة الجدول إلى أي ثانية داخل نافذة الاحتفاظ. PITR هو شبكة الأمان للحذف العرضي أو النشرات السيئة.
إذا احتجت إلى متانة متعددة المناطق أو قراءات بزمن منخفض بالقرب من المستخدمين، تُكرِّر Global Tables البيانات عبر المناطق المختارة. تُبسّط تخطيط الفشل، لكنها تدخل زمنًا للتأخير عبر المنطقة واعتبارات حل التعارض — لذا ابق أنماط الكتابة وملكية العنصر واضحة.
كحد أدنى، أنشئ تنبيهات على:
هذه الإشارات عادة ما تكشف عن مشاكل الشرائح الساخنة، سعة غير كافية، أو أنماط وصول غير متوقعة.
للتقييد، حدّد أولًا نمط الوصول المسبب، ثم خفف مؤقتًا بالتحويل إلى عند الطلب أو زيادة السعة المزودة، وفكر في تجزئة المفاتيح الساخنة.
للأعطال الجزئية أو الأخطاء المرتفعة، قلص دائرة التأثير: تعطيل الحركة غير الحرجة، أعد المحاولة بارتداد مع jitter، وفشل بشكل رحيم (مثال: تقديم قراءات مُخزَّنة مؤقتًا) حتى يستقر الجدول.
أمان DynamoDB يتعلق في الغالب بتضييق "من" يمكنه استدعاء أي إجراءات API، "من أين"، وعلى أي مفاتيح. لأن الجداول قد تحتوي على أنواع كيانات عديدة (وأحيانًا عدة مستأجرين)، ينبغي تصميم التحكم في الوصول جنبًا إلى جنب مع نموذج البيانات.
ابدأ بسياسات IAM قائمة على الهوية تُقيِّد الإجراءات (مثال: dynamodb:GetItem, Query, PutItem) إلى الحد الأدنى ونقِّحها لتشمل ARNs للجداول المعنية.
للتحكم الأدق، استخدم dynamodb:LeadingKeys لتقييد الوصول حسب قيم مفتاح التقسيم — مفيد عندما يجب أن يقرأ/يكتب خدمة أو مستأجر فقط في مساحة المفاتيح الخاصة به.
DynamoDB يُشفِّر البيانات في الراحة افتراضيًا باستخدام مفاتيح مملوكة من AWS أو مفتاح KMS مُدار من العميل. إذا كانت لديك متطلبات امتثال، فتأكد من:
للتشفير أثناء النقل، تأكد أن العملاء يستخدمون HTTPS (مكتبات AWS تفعل ذلك افتراضيًا). إذا أنهيت TLS في بروكسي، فتأكد أن الوصلة بين البروكسي وDynamoDB لا تزال مشفَّرة.
استخدم VPC Gateway Endpoint لـ DynamoDB حتى تبقى الحركة داخل شبكة AWS ويمكنك تطبيق سياسات نقطة النهاية لتقييد الوصول. اقترن هذا بضوابط الخروج (NACLs، مجموعات الأمان، والتوجيه) لتجنُّب مسارات "يمكن لأي شيء الوصول إلى الإنترنت العام".
للجداول المشتركة، أدرج معرف المستأجر في مفتاح التقسيم (مثال: TENANT#<id>)، ثم فَرض عزل المستأجر باستخدام شروط IAM على dynamodb:LeadingKeys.
إذا احتجت عزلًا أقوى، فكر في جداول منفصلة لكل مستأجر أو بيئة، واحتفظ بتصاميم الجداول المشتركة للحالات التي تفوق فيها بساطة التشغيل والاقتصاد مميزات حدود الانفجار الأصغر.
DynamoDB غالبًا ما يكون "رخيصًا عندما تكون دقيقًا، ومكلفًا عندما تكون غامضًا." تتبع التكاليف عادة أنماط الوصول، لذا يبدأ أفضل عمل تحسين بجعل تلك الأنماط صريحة.
فاتورتك تتشكل أساسًا من:
مفاجأة شائعة: كل كتابة إلى جدول هي أيضًا كتابة لكل GSI المتأثر، لذا "فهرس واحد إضافي" قد يضاعف تكلفة الكتابة.
تصميم المفاتيح الجيد يقلل الحاجة إلى عمليات مكلفة. إذا كثيرًا ما تلجأ إلى Scan فأنت تدفع لقراءة بيانات ستتخلص منها.
فضّل:
Query حسب مفتاح التقسيم (وبشكل اختياري شروط مفتاح الفرز)إذا كان نمط وصول نادرًا، فكّر في خدمته عبر جدول منفصل، مهمة ETL، أو نموذج قراءة مُخَصَّص بدلًا من GSI دائم.
استخدم TTL لحذف العناصر قصيرة العمر تلقائيًا (الجلسات، الرموز المؤقتة، حالات سير العمل المؤقتة). هذا يقلل التخزين ويمكن أن يصغر الفهارس مع الوقت.
لبيانات الزيادة (أحداث، سجلات)، اجمع TTL مع تصميم مفتاح فرز يتيح استعلام "الأحدث فقط" بحيث لا تلامس التاريخ البارد غالبًا.
في الوضع المزود، ضع خطوط أساس محافظة وقم بالتدرج مع autoscaling استنادًا إلى مقاييس حقيقية. في وضع عند الطلب، راقب الأنماط غير الفعالة (عناصر كبيرة، عملاء كثير الطلبات) التي تقود حجم الطلب.
عامل Scan كملاذ أخير — عندما تحتاج معالجة الجدول الكامل حقًا، جدوله خارج أوقات الذروة أو نفّذه كدُفعة مُتحكم بها مع ترقيم صفحات وارتداد.
DynamoDB تتألق عندما يمكن التعبير عن تطبيقك كمجموعة من أنماط الوصول المحددة جيدًا وتحتاج زمن استجابة منخفض ثابت على نطاق كبير. إذا استطعت وصف قراءاتك وكتاباتك مقدمًا (بواسطة مفتاح التقسيم، مفتاح الفرز، وعدد قليل من الفهارس)، فهي غالبًا إحدى أبسط الطرق لتشغيل مخزن بيانات عالي التوافر.
DynamoDB خيار قوي عندما تمتلك:
ابحث في أماكن أخرى إذا كانت متطلباتك الأساسية تشمل:
العديد من الفرق تحتفظ بـ DynamoDB للقراءات والكتابات "الساخنة" التشغيلية، ثم تضيف:
إذا كنت تتحقق من أنماط الوصول واتفاقيات الجدول الواحد، فالأهمية للسرعة. قد تُسرع الفرق النماذج المحيطة والخط الأمامي في منصات برمجة سريعة ثم تعدِّل تصميم مفاتيح DynamoDB كلما ظهرت مسارات استعلام حقيقية. حتى لو اختلفت البنية الإنتاجية، تساعد النماذج الطرفية على كشف أي استعلامات يجب أن تكون Query مقابل أي شيء قد يتحول بطريق الخطأ إلى Scan.
تحقق: (1) استعلاماتك العُليا معروفة ومعتمدة على المفاتيح، (2) احتياجات الصحة المنطقية تتوافق مع نموذج التناسق، (3) أحجام العناصر والنمو متوقعان، و(4) نموذج التكلفة (عند الطلب مقابل مزود + autoscaling) يناسب ميزانيتك.
DynamoDB هي قاعدة بيانات NoSQL مُدارة بالكامل على AWS مصمَّمة لـ قراءات/كتابات بزمن استجابة منخفض وثابت على نطاق كبير جدًا. تختارها الفرق عندما يمكنها تحديد نماذج وصول قائمة على المفاتيح (جلب بواسطة المعرف، قوائم حسب المالك، استعلامات بنطاق زمني) وتريد تجنُّب تشغيل البنية التحتية لقاعدة البيانات.
تشيع استخدامها في الخدمات المصغرة، التطبيقات الخالية من الخوادم (serverless)، والأنظمة المعتمدة على الأحداث.
الجدول يحتوي على عناصر (مثل الصفوف). كل عنصر هو مجموعة مرنة من السمات (مثل الأعمدة) ويمكن أن يتضمن بيانات متداخلة.
تعمل DynamoDB جيدًا عندما يحتاج الطلب عادةً إلى “الكيان بأكمله”، لأن العناصر يمكن أن تحتوي على خرائط وقوائم (هياكل شبيهة بـ JSON).
مفتاح التقسيم بمفرده يعرّف العنصر بشكل فريد (مفتاح أولي بسيط). مفتاح التقسيم + مفتاح الفرز (مفتاح مركب) يتيح لعدة عناصر مشاركة نفس مفتاح التقسيم مع التمييز بينهما وترتيبها عبر مفتاح الفرز.
المفاتيح المركبة تُمكّن أنماط مثل:
استخدم Query عندما يمكنك تحديد مفتاح التقسيم (وبشكل اختياري شرط على مفتاح الفرز). هذا المسار هو السريع والقابل للتدرج.
استخدم Scan فقط عندما تحتاج فعليًا لقراءة كل شيء؛ فهو يمسح الجدول أو الفهرس ثم يفلتر النتائج، وعادةً ما يكون أبطأ وأكثر تكلفة.
إذا كنت تقوم بعمليات مسح متكررة، فهذه إشارة إلى أن تصميم المفتاح أو الفهرس يحتاج إلى تعديل.
الفهارس الثانوية توفر مسارات استعلام بديلة.
تزيد الفهارس من تكلفة الكتابة لأن كل كتابة تُنسخ أيضًا إلى الفهرس.
اختر On-Demand إذا كان المرور غير متوقع، متقلبًا، أو لا تريد إدارة السعة. الدفع يكون حسب الطلب.
اختر Provisioned إذا كان الاستخدام ثابتًا/قابل للتنبؤ وتريد تكلفة أكثر تحكمًا. اقترن مع autoscaling، لكن تذكّر أنه قد لا يستجيب فورًا للارتفاعات المفاجئة.
بشكل افتراضي، القراءات متسقة بصورة نهائية (eventually consistent)، بمعنى أنك قد ترى قيمة قديمة لفترة وجيزة بعد الكتابة.
استخدم القراءات المتسقة بقوة عندما تحتاج إلى رؤية أحدث كتابة مؤكَّدة، مثل فحوصات الجوازات أو حالات سير العمل الحرجة.
ولتصحيح التوازي، فضّل التحديثات الذرية (مثل UpdateItem مع ADD) بدلًا من حلقات القراءة-تعديل-الكتابة.
توفر المعاملات (TransactWriteItems, TransactGetItems) خصائص ACID عبر ما يصل إلى 25 عنصرًا.
استخدمها عندما تحتاج إلى تحديث عدة عناصر معًا (مثال: إنشاء طلب وحجز مخزون) أو لفرض قواعد لا تحتمل حالات وسيطة.
المعاملات تكلف أكثر وقد تزيد زمن الاستجابة، لذا استخدمها فقط في المسارات التي تتطلبها حقًا.
تصبح الشرائح الساخنة عندما يستهدف الكثير من الطلبات نفس قيمة مفتاح التقسيم (أو مجموعة صغيرة من القيم)، مما يسبب تقييدًا حتى لو كان الجدول ككل غير مستغلّ.
تدابير شائعة:
فَعِّل DynamoDB Streams للحصول على تغذية تغيرات عند الإدراج، التحديث، والحذف. نمط شائع هو Streams → Lambda لتحفيز معالجة لاحقة.
الضمانات المهمة التي يجب التصميم لها:
اجعل المستهلكين (upsert بحسب المفتاح، أو استخدام كتابات شرطية، أو تتبع معرفات الأحداث المعالجة).
GetItemPK = USER#<id>, SK begins_with ORDER# (أو SK = CREATED_AT#...)PK = DEVICE#<id>, SK = TS#<timestamp> مع BETWEEN لنوافذ زمنية