أمازون دينامو دي بي
| المطور(ون) | أمازون.كوم |
|---|---|
| الإصدار الأولي | يناير 2012 [1] |
| مكتوب في | جافا |
| نظام التشغيل | متعدد المنصات |
| متوفر في | إنجليزي |
| يكتب | |
| رخصة | الملكية |
| موقع إلكتروني | aws.amazon.com/dynamodb/ |
Amazon DynamoDB هي قاعدة بيانات NoSQL مملوكة بالكامل ومدارة تقدمها Amazon.com كجزء من مجموعة خدمات الويب من Amazon . [2] [3] تقدم DynamoDB مخزن بيانات سريع ومستمر للقيمة الرئيسية مع دعم مدمج للتكرار والتوسع التلقائي والتشفير في وضع السكون والنسخ الاحتياطي عند الطلب من بين ميزات أخرى. [4] [5]
خلفية
قدم فيرنر فوجيلز ، كبير مسؤولي التكنولوجيا في أمازون دوت كوم، دافعًا للمشروع في إعلانه عام 2012. [6] بدأت أمازون كشبكة لامركزية من الخدمات. في الأصل، كان للخدمات وصول مباشر إلى قواعد بيانات بعضها البعض. وعندما أصبح هذا يشكل عنق زجاجة في عمليات الهندسة، ابتعدت الخدمات عن نمط الوصول المباشر هذا لصالح واجهات برمجة التطبيقات التي تواجه الجمهور. ومع ذلك، واجهت أنظمة إدارة قواعد البيانات العلائقية التابعة لجهات خارجية صعوبة في التعامل مع قاعدة عملاء أمازون. بلغ هذا ذروته خلال موسم العطلات لعام 2004 [7] [8] ، عندما فشلت العديد من التقنيات في ظل حركة مرور عالية.
كان المهندسون يقومون بتطبيع هذه الأنظمة العلائقية لتقليل تكرار البيانات ، وهو تصميم يعمل على تحسين التخزين. التضحية: لقد قاموا بتخزين "عنصر" معين من البيانات (على سبيل المثال، المعلومات المتعلقة بمنتج في قاعدة بيانات المنتج) على عدة علاقات، ويستغرق تجميع الأجزاء المنفصلة للاستعلام وقتًا طويلاً. تطلبت العديد من خدمات أمازون قراءات مفتاحية أساسية في الغالب على بياناتها، ومع السرعة كأولوية قصوى، كان تجميع هذه الأجزاء معًا أمرًا شاقًا للغاية. [9]
كانت استجابة أمازون، التي كانت راضية عن التضحية بكفاءة التخزين، هي Dynamo : وهو مخزن قيم رئيسي عالي التوفر تم تصميمه للاستخدام الداخلي. [6] بدا أن Dynamo هو كل ما يحتاجه مهندسوهم، لكن التبني تأخر. اختار مطورو أمازون أنماط التصميم "المناسبة" مع S3 و SimpleDB. وبينما كانت هذه الأنظمة تعاني من عيوب تصميمية ملحوظة، إلا أنها لم تتطلب تكلفة تجهيز الأجهزة وتوسيع نطاق البيانات وإعادة تقسيمها. قامت DynamoDB، الإصدار التالي من تقنية NoSQL من أمازون ، بأتمتة عمليات إدارة قواعد البيانات هذه.
ملخص

في DynamoDB، يتم تخزين البيانات في الجداول كعناصر ، ويمكن الاستعلام عنها باستخدام الفهارس. تتكون العناصر من عدد من السمات التي يمكن أن تنتمي إلى عدد من أنواع البيانات ، ويجب أن يكون لها مفتاح من المتوقع أن يكون فريدًا عبر الجدول.
جداول DynamoDB
جدول DynamoDB عبارة عن مجموعة منطقية من العناصر التي تمثل البيانات المخزنة في هذا الجدول. ونظرًا لطبيعة NoSQL في DynamoDB، فإن الجداول لا تتطلب أن تتوافق جميع العناصر في الجدول مع مخطط محدد مسبقًا. [10]
عناصر DynamoDB
العنصر في DynamoDB عبارة عن مجموعة من السمات التي يمكن التعرف عليها بشكل فريد في جدول. السمة هي كيان بيانات ذري وهو في حد ذاته زوج من المفتاح والقيمة. يكون المفتاح دائمًا من نوع سلسلة، بينما يمكن أن تكون القيمة من أحد أنواع البيانات المتعددة.
يتم التعرف على العنصر بشكل فريد في جدول باستخدام مجموعة فرعية من سماته تسمى المفاتيح. [10]
المفاتيح في DynamoDB
المفتاح الأساسي هو مجموعة من السمات التي تحدد بشكل فريد العناصر في جدول DynamoDB. يتطلب إنشاء جدول DynamoDB تعريف مفتاح أساسي. يجب أن يحتوي كل عنصر في جدول DynamoDB على جميع السمات التي تشكل المفتاح الأساسي، ولا يمكن أن يكون لعنصرين في جدول نفس المفتاح الأساسي. يمكن أن تتكون المفاتيح الأساسية في Dynamo DB من سمة واحدة أو سمتين.
عندما يتكون المفتاح الأساسي من سمة واحدة فقط، يُطلق عليه اسم مفتاح التقسيم. تحدد مفاتيح التقسيم الموقع الفعلي للعنصر المرتبط. في هذه الحالة، لا يمكن أن يكون لعنصرين في جدول نفس مفتاح التقسيم.
عندما يتكون المفتاح الأساسي من خاصيتين، تسمى الأولى "مفتاح التقسيم" وتسمى الثانية "مفتاح الفرز". وكما كان الحال من قبل، يحدد مفتاح التقسيم الموقع المادي للبيانات، لكن مفتاح الفرز يقرر بعد ذلك الموضع المنطقي النسبي لسجل العنصر المرتبط داخل هذا الموقع المادي. في هذه الحالة، يمكن أن يكون لعنصرين في جدول نفس مفتاح التقسيم، لكن لا يمكن لعنصرين في قسم أن يكون لهما نفس مفتاح الفرز. بعبارة أخرى، من المضمون أن يكون لمجموعة معينة من مفتاح التقسيم ومفتاح الفرز عنصر واحد على الأكثر مرتبط بها في جدول DynamoDB. [10]
أنواع بيانات DynamoDB
يدعم DynamoDB أنواع البيانات الرقمية والسلاسل والمنطقية والمستندية والمحددة. [11]
مؤشرات DynamoDB
المفتاح الأساسي للجدول هو الفهرس الافتراضي أو الأساسي لجدول DynamoDB.
بالإضافة إلى ذلك، يمكن أن يحتوي جدول DynamoDB على فهرس ثانوي. يتم تعريف الفهرس الثانوي على سمة مختلفة عن مفتاح القسم أو مفتاح الفرز باعتباره الفهرس الأساسي.
عندما يكون للمؤشر الثانوي مفتاح تقسيم مماثل للمؤشر الأساسي ولكن مفتاح فرز مختلف، يُطلق عليه اسم المؤشر الثانوي المحلي.
عندما يكون للمؤشر الأساسي والمؤشر الثانوي مفتاح تقسيم مختلف، يُعرف المؤشر الثانوي بالمؤشر الثانوي العالمي. [10]
اعتبارات التطوير
بناء الجملة
يستخدم DynamoDB JSON لقواعده النحوية نظرًا لانتشاره. [ بحاجة لمصدر ] يتطلب إجراء إنشاء جدول ثلاثة وسيطات فقط: TableName وKeySchema - قائمة تحتوي على مفتاح تقسيم ومفتاح فرز اختياري - وAttributeDefinitions - قائمة بالسمات المراد تعريفها والتي يجب أن تحتوي على الأقل على تعريفات للسمات المستخدمة كمفاتيح تقسيم وفرز. في حين توفر قواعد البيانات العلائقية لغات استعلام قوية، تقدم DynamoDB عمليات Put وGet وUpdate وDelete فقط. تحتوي طلبات Put على سمة TableName وسمة Item، والتي تتكون من جميع السمات والقيم التي يحتوي عليها العنصر. يتبع طلب التحديث نفس قواعد اللغة. وبالمثل، للحصول على عنصر أو حذفه، ما عليك سوى تحديد TableName وKey.
هندسة النظام

هياكل البيانات
تستخدم DynamoDB التجزئة وأشجار B لإدارة البيانات. عند الإدخال، يتم توزيع البيانات أولاً على أقسام مختلفة عن طريق التجزئة على مفتاح القسم. يمكن لكل قسم تخزين ما يصل إلى 10 جيجابايت من البيانات والتعامل بشكل افتراضي مع 1000 وحدة سعة كتابة (WCU) و3000 وحدة سعة قراءة (RCU). [12] تمثل وحدة RCU واحدة قراءة واحدة متسقة بقوة في الثانية أو قراءتين متسقتين في النهاية في الثانية لعناصر يصل حجمها إلى 4 كيلوبايت. [13] تمثل وحدة WCU واحدة كتابة واحدة في الثانية لعنصر يصل حجمه إلى 1 كيلوبايت.
لمنع فقدان البيانات، يتميز DynamoDB بنظام نسخ احتياطي من مستويين للتكرار والتخزين طويل الأمد. [14] يتميز كل قسم بثلاث عقد، تحتوي كل منها على نسخة من بيانات هذا القسم. تحتوي كل عقدة أيضًا على بنيتين للبيانات: شجرة B تستخدم لتحديد موقع العناصر، وسجل تكرار يلاحظ جميع التغييرات التي تم إجراؤها على العقدة. يأخذ DynamoDB بشكل دوري لقطات من بنيتي البيانات هاتين ويخزنها لمدة شهر في S3 حتى يتمكن المهندسون من إجراء عمليات استعادة في نقطة زمنية لقواعد البيانات الخاصة بهم.
داخل كل قسم، يتم تعيين إحدى العقد الثلاث على أنها "عقدة القائد". تنتقل جميع عمليات الكتابة أولاً عبر العقدة القائدة قبل الانتشار، مما يجعل عمليات الكتابة متسقة في DynamoDB. للحفاظ على حالتها، ترسل العقدة القائدة "نبضة قلب" إلى كل عقدة أخرى كل 1.5 ثانية. إذا توقفت عقدة أخرى عن تلقي نبضات القلب، فيمكنها بدء انتخاب قائد جديد. يستخدم DynamoDB خوارزمية Paxos لانتخاب القادة.
تجنب مهندسو أمازون في الأصل استخدام Dynamo بسبب النفقات الهندسية مثل توفير وإدارة الأقسام والعقد. [9] واستجابة لذلك، قام فريق DynamoDB ببناء خدمة يطلق عليها AutoAdmin لإدارة قاعدة البيانات. [14] يستبدل AutoAdmin العقدة عندما تتوقف عن الاستجابة عن طريق نسخ البيانات من عقدة أخرى. عندما يتجاوز القسم أيًا من عتباته الثلاثة (RCU أو WCU أو 10 جيجابايت)، سيضيف AutoAdmin تلقائيًا أقسامًا إضافية لتقسيم البيانات بشكل أكبر. [12]
تمامًا مثل أنظمة الفهرسة في النموذج العلائقي، تطلب DynamoDB أن تنعكس أي تحديثات على جدول في كل من فهارس الجدول. تتعامل DynamoDB مع هذا باستخدام خدمة تسمى "مُروّج السجل"، والتي تشترك في سجلات التكرار في كل عقدة وترسل طلبات وضع وتحديث وحذف إضافية إلى الفهارس حسب الضرورة. [14] نظرًا لأن الفهارس تؤدي إلى انخفاض كبير في الأداء لطلبات الكتابة، فإن DynamoDB تسمح للمستخدم بخمسة منها على الأكثر في أي جدول معين. [15]
تنفيذ الاستعلام
لنفترض أن مستخدم DynamoDB أصدر عملية كتابة (وضع أو تحديث أو حذف). في حين أن النظام العلائقي النموذجي يحول استعلام SQL إلى جبر علائقي ويشغل خوارزميات التحسين، فإن DynamoDB يتخطى كلتا العمليتين ويبدأ العمل على الفور. [14] يصل الطلب إلى موجه طلبات DynamoDB، الذي يقوم بالتحقق من صحة - "هل يأتي الطلب من أين/من يدعي أنه؟" - ويتحقق من التفويض - "هل لدى المستخدم الذي يرسل الطلب الأذونات المطلوبة؟" بافتراض نجاح هذه الفحوصات، يقوم النظام بتجزئة مفتاح قسم الطلب للوصول إلى القسم المناسب. هناك ثلاث عقد بالداخل، كل منها بنسخة من بيانات القسم. يكتب النظام أولاً إلى العقدة الرئيسية، ثم يكتب إلى عقدة ثانية، ثم يرسل رسالة "نجاح"، وأخيرًا يستمر في الانتشار إلى العقدة الثالثة. تكون عمليات الكتابة متسقة لأنها تنتقل دائمًا أولاً عبر العقدة الرئيسية.
أخيرًا، ينشر مُروّج السجل التغيير إلى جميع الفهارس. لكل فهرس، يلتقط قيمة المفتاح الأساسي لهذا الفهرس من العنصر، ثم يقوم بنفس الكتابة على هذا الفهرس دون نشر السجل. إذا كانت العملية تحديثًا لعنصر موجود مسبقًا، فقد تعمل السمة المُحدّثة كمفتاح أساسي للفهرس، وبالتالي يجب تحديث شجرة B لهذا الفهرس أيضًا. تتعامل أشجار B فقط مع عمليات الإدراج والحذف والقراءة، لذلك في الممارسة العملية، عندما يستقبل مُروّج السجل عملية تحديث، فإنه يصدر كلًا من عملية الحذف وعملية وضع لجميع الفهارس.
الآن لنفترض أن مستخدم DynamoDB أصدر عملية Get. يستمر موجه الطلب كما كان من قبل مع المصادقة والترخيص. بعد ذلك، كما هو مذكور أعلاه، نقوم بتجزئة مفتاح القسم الخاص بنا للوصول إلى التجزئة المناسبة. الآن، نواجه مشكلة: مع وجود ثلاث عقد متسقة في النهاية مع بعضها البعض، كيف يمكننا تحديد أي منها يجب التحقق منها؟ تقدم DynamoDB للمستخدم خيارين عند إصدار قراءة: متسقة ومتسقة في النهاية. تزور القراءة المتسقة العقدة الرئيسية. لكن المقايضة بين الاتساق والتوافر تظهر مرة أخرى هنا: في الأنظمة التي تعتمد على القراءة بشكل كبير، يمكن للقراءة دائمًا من العقدة الرئيسية أن تطغى على عقدة واحدة وتقلل من التوافر.
الخيار الثاني، القراءة المتسقة في النهاية ، يختار عقدة عشوائية. في الممارسة العملية، هذا هو المكان الذي يتاجر فيه DynamoDB بالاتساق من أجل التوافر. إذا سلكنا هذا المسار، فما هي احتمالات عدم الاتساق؟ سنحتاج إلى عملية كتابة لإرجاع "النجاح" والبدء في الانتشار إلى العقدة الثالثة، ولكن ليس الانتهاء. سنحتاج أيضًا إلى أن يستهدف Get هذه العقدة الثالثة. وهذا يعني فرصة 1 من 3 لعدم الاتساق داخل نافذة انتشار عملية الكتابة. ما طول هذه النافذة؟ يمكن لأي عدد من الكوارث أن يتسبب في تأخر العقدة، ولكن في الغالبية العظمى من الحالات، تكون العقدة الثالثة محدثة في غضون مللي ثانية من العقدة الرائدة.
أداء

يعرض DynamoDB مقاييس الأداء التي تساعد المستخدمين على توفيرها بشكل صحيح والحفاظ على تشغيل التطبيقات التي تستخدم DynamoDB بسلاسة:
- الطلبات والتضييق
- الأخطاء: ProvisionedThroughputExceededException،ConditionalCheckFailedException،خطأ داخلي في الخادم (HTTP 500)
- المقاييس المتعلقة بإنشاء المؤشر الثانوي العالمي [16]
يمكن تتبع هذه المقاييس باستخدام وحدة التحكم الإدارية في AWS ، أو باستخدام واجهة سطر أوامر AWS ، أو أداة مراقبة متكاملة مع Amazon CloudWatch . [17]
أفضل الممارسات
يجب على مطوري DynamoDB: [18]
- تحديد أنماط الوصول إلى البيانات
- استخدم الأحداث بدلاً من الاستطلاع
روابط اللغة
تتضمن اللغات والأطر المرتبطة بـ DynamoDB كل من Java و JavaScript و Node.js و Go و C# .NET و Perl و PHP و Python و Ruby و Rust و Haskell و Erlang و Django و Grails . [19]
أمثلة التعليمات البرمجية
.png/440px-Aws-dynamodb-webconsole-item_(cropped).png)
واجهة برمجة التطبيقات HTTP
مقابل واجهة برمجة تطبيقات HTTP، عناصر الاستعلام:
POST / HTTP / 1.1
المضيف : dynamodb.<region>.<domain>؛
Accept-Encoding : identity
Content-Length : <PayloadSizeBytes>
وكيل المستخدم : <UserAgentString>
نوع المحتوى : application/x-amz-json-1.0
التفويض : AWS4-HMAC-SHA256 بيانات الاعتماد=<Credential>، رؤوس التوقيع=<Headers>، التوقيع=<Signature>
تاريخ X-Amz : <Date>
هدف X-Amz : DynamoDB_20120810.Query
{
"TableName": "الرد"،
"IndexName": "PostedBy-Index"،
"الحد": 3،
"ConsistentRead": صحيح،
"ProjectionExpression": "المعرف، المنشور بواسطة، تاريخ ووقت الرد"،
"KeyConditionExpression": "المعرف = :v1 وPostedBy بين :v2a و :v2b"،
"قيم سمة التعبير": {
":v1": {"S": "Amazon DynamoDB#DynamoDB Thread 1"},
":v2a": {"S": "المستخدم أ"},
":v2b": {"S": "المستخدم C"}
},
"ReturnConsumedCapacity": "الإجمالي"
}
نموذج الرد:
HTTP / 1.1 200 OK
x-amzn-RequestId : <RequestId>
x-amz-crc32 : <Checksum>
Content-Type : application/x-amz-json-1.0
Content-Length : <PayloadSizeBytes>
Date : <Date>
{
"ConsumedCapacity": {
"CapacityUnits": 1,
"TableName": "Reply"
},
"Count": 2,
"Items": [
{
"ReplyDateTime": {"S": "2015-02-18T20:27:36.165Z"},
"PostedBy": {"S": "User A"},
"Id": {"S": "Amazon DynamoDB#DynamoDB Thread 1"}
},
{
"ReplyDateTime": {"S": "2015-02-25T20:27:36.165Z"،
"PostedBy": {"S": "User B"}،
"Id": {"S": "Amazon DynamoDB#DynamoDB Thread 1"}
]
،
"ScannedCount": 2
}
يذهب
GetItem في Go :
getItemInput := & dynamodb . GetItemInput { TableName : aws . String ( "happy-marketer" ) , Key : map [ string ] * dynamodb . AttributeValue { "pk" : { S : aws . String ( "project" ) , }, "sk" : { S : aws . String ( email + " " + name ), } , } getItemOutput , err := dynamodbClient . GetItem ( getItemInput )
حذف العنصر في Go :
deleteItemInput := & dynamodb . DeleteItemInput { TableName : aws . String ( "happy-marketer" ) , Key : map [ string ] * dynamodb . AttributeValue { "pk" : { S : aws . String ( "project" ) , }, "sk" : { S : aws . String ( email + " " + name ), } , }
_ ، err := dynamodbClient . DeleteItem ( deleteItemInput ) إذا لم يكن err = nil { panic ( err ) }
تحديث العنصر في Go باستخدام Expression Builder:
التحديث := تعبير . تعيين ( تعبير . اسم ( اسم )، تعبير . قيمة ( قيمة )، )
expr ، err := expression . NewBuilder (). WithUpdate ( update ). Build () إذا لم يكن err = nil { panic ( err ) }
updateItemInput := & dynamodb.UpdateItemInput { TableName : aws.String ( tableName ) , Key : map [ string ] * dynamodb.AttributeValue { " pk " : { S : aws.String ( " project" ), }, " sk" : { S : aws.String ( " mySortKeyValue" ) , } , } , UpdateExpression : expr.Update ( ), ExpressionAttributeNames : expr.Names (), ExpressionAttributeValues : expr.Values ( ) , } fmt.Printf ( " updateItemInput : % # v\n " , updateItemInput )
_ ، err = dynamodbClient.UpdateItem ( updateItemInput ) إذا لم يكن err = nil { panic ( err ) }
انظر أيضا
- أمازون أورورا
- قاعدة بيانات أمازون للوثائق
- أمازون ريدشيفت
- خدمة قاعدة بيانات أمازون العلائقية
- ScyllaDB (متوافق مع DynamoDB)
- مقارنة بين أنظمة إدارة قواعد البيانات العلائقية
مراجع
- ^ "Amazon DynamoDB – خدمة قاعدة بيانات NoSQL سريعة وقابلة للتطوير ومصممة للتطبيقات التي يمكن تطبيقها على نطاق واسع على الإنترنت – All Things Distributed". www.allthingsdistributed.com . 18 يناير 2012.
- ^ كلارك، جاك (2012-01-19). "أمازون تبدأ تشغيل خدمة قاعدة البيانات السحابية DynamoDB". ZDNet . تم الاسترجاع في 2012-01-21 .
- ^ "قاعدة بيانات سريعة لقيم المفاتيح NoSQL – Amazon DynamoDB – Amazon Web Services". Amazon Web Services, Inc. تم الاسترجاع في 2023-05-28 .
- ^ "ميزات Amazon DynamoDB | قاعدة بيانات القيمة الرئيسية NoSQL | Amazon Web Services". Amazon Web Services, Inc. تم الاسترجاع في 2023-05-28 .
- ^ "ما هو Amazon DynamoDB؟ - Amazon DynamoDB". docs.aws.amazon.com . تم الاسترجاع في 2023-05-28 .
- ^ ab Vogels, Werner (2012-01-18). "Amazon DynamoDB – a Fast and Scalable NoSQL Database Service Designed for Internet Scale Applications". مدونة All Things Distributed . تم الاسترجاع في 2012-01-21 .
- ^ "كيف ساعد DynamoDB من Amazon في إعادة اختراع قواعد البيانات". Network World . تم الاسترجاع في 2023-11-30 .
- ^ brockmeier 1, joe (2012-01-18). "Amazon Takes Another Pass at NoSQL with DynamoDB". ReadWrite . تم الاسترجاع في 2023-11-30 .
{{cite web}}:CS1 maint: أسماء رقمية: قائمة المؤلفين ( الرابط ) - ^ أب ديكانديا ، جوزيبي. هستورون، دنيز؛ جامباني، مادان؛ كاكولاباتي، جونافاردان؛ لاكشمان، أفيناش؛ بيلشين، اليكس. سيفاسوبرامانيان، سواميناثان؛ فوسشال، بيتر؛ فوجلز ، فيرنر (أكتوبر 2007). “دينامو: متجر أمازون ذو القيمة الرئيسية والمتوفر للغاية”. سيجوبس أوبر. النظام. القس . 41 (6): 205-220. دوى :10.1145/1323293.1294281. ISSN 0163-5980.
- ^ abcd "المكونات الأساسية لـ Amazon DynamoDB - Amazon DynamoDB". docs.aws.amazon.com . تم الاسترجاع في 2023-05-28 .
- ^ "أنواع البيانات المدعومة وقواعد التسمية في Amazon DynamoDB - Amazon DynamoDB". docs.aws.amazon.com . تم الاسترجاع في 2023-05-28 .
- ^ من قبل Gunasekara، Archie (2016-06-27). "A Deep Dive into DynamoDB Partitions". Shine Solutions Group . تم الاسترجاع في 2019-08-03 .
- ^ "دليل مطوري Amazon DynamoDB". AWS . 10 أغسطس 2012. تم الاسترجاع في 18 يوليو 2019 .
- ^ abcd AWS re:Invent 2018: Amazon DynamoDB Under the Hood: How We Build a Hyper-Scale Database (DAT321)، 27 نوفمبر 2018 ، تم الاسترجاع في 2019-08-03
- ^ "حصص الخدمة والحساب والجدول في Amazon DynamoDB - Amazon DynamoDB". docs.aws.amazon.com . تم الاسترجاع في 2024-01-09 .
- ^ "أهم مقاييس أداء DynamoDB". 15 سبتمبر 2015.
- ^ "كيفية جمع مقاييس DynamoDB". 15 سبتمبر 2015.
- ^ ديبري، أليكس (2020). كتاب DynamoDB . نُشر بشكل مستقل. رقم ISBN 979-8365145672.
- ^ "مكتبات Amazon DynamoDB، وMappers، وتطبيقات وهمية كثيرة!". Amazon Web Services . 5 أبريل 2012.
روابط خارجية
- الموقع الرسمي
- فيديو: AWS re:Invent 2019: [REPEAT 1] نظرة متعمقة على Amazon DynamoDB: أنماط التصميم المتقدمة (DAT403-R1)
