تصميم البيانات في Azure Cosmos DB

ينطبق على: NoSQL

بينما تجعل قواعد البيانات الخالية من المخططات، مثل Azure Cosmos DB، من السهل جداً تخزين البيانات غير المهيكلة وشبه المنظمة والاستعلام عنها، يجب عليك قضاء بعض الوقت في التفكير في نموذج البيانات الخاص بك للحصول على أقصى استفادة من الخدمة من حيث الأداء وقابلية التوسع وبأقل تكلفة.

كيف سيتم تخزين البيانات؟ كيف سيقوم تطبيقك باسترداد البيانات والاستعلام عنها؟ هل التطبيق الخاص بك ثقيل القراءة أم الكتابة ثقيلة؟

بعد قراءة هذا المقال، ستتمكن من الإجابة على الأسئلة التالية:

  • ما هي نمذجة البيانات ولماذا يجب أن أهتم؟
  • كيف تختلف نمذجة البيانات في Azure Cosmos DB عن قاعدة البيانات الارتباطية؟
  • كيف أعبر عن ارتباطات البيانات في قاعدة بيانات غير علائقية؟
  • متى أقوم بتضمين البيانات ومتى أقوم بالربط بالبيانات؟

الأرقام في JSON

يحفظ Azure Cosmos DB المستندات في JSON. مما يعني أنه من الضروري تحديد ما إذا كان من الضروري تحويل الأرقام إلى سلاسل قبل تخزينها في json أم لا. يجب تحويل جميع الأرقام بشكل مثالي إلى String، إذا كانت هناك أي فرصة أنها خارج حدود أرقام الدقة المزدوجة وفقا ل IEEE 754 binary64. توضح مواصفات Json الأسباب التي تجعل استخدام الأرقام خارج هذه الحدود ممارسةً سيئةً بوجهٍ عامٍ بسبب مشاكل إمكانية التشغيل التفاعلي المحتملة. هذه المخاوف ذات صلة بعمود مفتاح القسم بوجهٍ خاصٍ، لأنه غير قابل للتغيير ويتطلب ترحيل البيانات لتغييره لاحقاً.

البيانات المتضمنة

عند بدء نمذجة البيانات في Azure Cosmos DB، حاول معاملة الكيانات الخاصة بك على أنها عناصر قائمة بذاتها ممثلة كمستندات JSON.

للمقارنة، دعنا أولاً نرى كيف يمكننا نمذجة البيانات في قاعدة بيانات علائقية. يوضح المثال التالي كيف يمكن تخزين الشخص في قاعدة بيانات علائقية.

نموذج قاعدة البيانات الارتباطية

تتمثل الاستراتيجية، عند العمل مع قواعد البيانات الارتباطية، في تطبيع جميع بياناتك. تتضمن تسوية بياناتك عادةً أخذ كيان، مثل شخص، وتقسيمه إلى مكونات منفصلة. في المثال أعلاه، يمكن أن يكون لدى شخص سجلات تفاصيل جهات اتصال متعددة، والعديد من سجلات العناوين. يمكن تقسيم تفاصيل الاتصال بشكل أكبر عن طريق استخراج المزيد من الحقول المشتركة مثل النوع. الأمر نفسه ينطبق على العنوان، يمكن أن يكون كل سجل من نوع الصفحة الرئيسية أو الأعمال .

إن الفرضية الإرشادية عند تسوية البيانات هي تجنب تخزين البيانات الزائدة عن الحاجة في كل سجل وبدلاً من الإشارة إلى البيانات. في هذا المثال، لقراءة شخص ما، بكل تفاصيل الاتصال والعناوين الخاصة به، تحتاج إلى استخدام JOINS لإعادة إنشاء (أو إلغاء تنسيق) بياناتك بشكل فعال في وقت التشغيل.

SELECT p.FirstName, p.LastName, a.City, cd.Detail
FROM Person p
JOIN ContactDetail cd ON cd.PersonId = p.Id
JOIN ContactDetailType cdt ON cdt.Id = cd.TypeId
JOIN Address a ON a.PersonId = p.Id

إن عمليات الكتابة عبر العديد من الجداول الفردية مطلوبة لتحديث تفاصيل الاتصال والعناوين الخاصة بشخص واحد.

الآن دعونا نلقي نظرة على كيفية نمذجة نفس البيانات ككيان قائم بذاته في Azure Cosmos DB.

{
    "id": "1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "addresses": [
        {
            "line1": "100 Some Street",
            "line2": "Unit 1",
            "city": "Seattle",
            "state": "WA",
            "zip": 98012
        }
    ],
    "contactDetails": [
        {"email": "thomas@andersen.com"},
        {"phone": "+1 555 555-5555", "extension": 5555}
    ]
}

باتباع الطريقة أعلاه، نشرنا تكرار سجل الشخص، من خلال تضمين جميع المعلومات المتعلقة بهذا الشخص، مثل تفاصيل جهات الاتصال والعناوين، في مستند JSON فردي. بالإضافة إلى ذلك، نظراً لأننا لا نقتصر على مخطط ثابت، فإننا نتمتع بالمرونة للقيام بأشياء مثل الحصول على تفاصيل اتصال بأشكال مختلفة تماماً.

أصبح استرداد سجل شخص كامل من قاعدة البيانات الآن عملية قراءة واحدة مقابل حاوية واحدة ولعنصر واحد. إن تحديث تفاصيل الاتصال والعناوين الخاصة بسجل شخص هي أيضاً عملية كتابة واحدة مقابل عنصر واحد.

من خلال إلغاء تنسيق البيانات، قد يحتاج تطبيقك إلى إصدار عدد أقل من الاستعلامات والتحديثات لإكمال العمليات المشتركة.

متى يتم التضمين

بشكل عام، استخدم نماذج البيانات المضمنة عندما:

  • هناك ارتباطات واردة بين الكيانات.
  • هناك ارتباطات فردية بين الكيانات.
  • ثمة بيانات مضمنة تتغير بشكل غير متكرر.
  • ثمة بيانات مضمنة لن تزداد بدون ربط.
  • ثمة بيانات مضمنة يتم الاستعلام عنها بشكل متكرر معاً.

ملاحظة

توفر نماذج البيانات التي لم تتم تسويتها عادةً أداء قراءة أفضل.

عندما لا يتم التضمين

في حين أن القاعدة الأساسية في Azure Cosmos DB هي إلغاء تسوية كل شيء وتضمين جميع البيانات في عنصر واحد، يمكن أن يؤدي ذلك إلى بعض المواقف التي يجب تجنبها.

خذ هذا المقتطف JSON.

{
    "id": "1",
    "name": "What's new in the coolest Cloud",
    "summary": "A blog post by someone real famous",
    "comments": [
        {"id": 1, "author": "anon", "comment": "something useful, I'm sure"},
        {"id": 2, "author": "bob", "comment": "wisdom from the interwebs"},
        …
        {"id": 100001, "author": "jane", "comment": "and on we go ..."},
        …
        {"id": 1000000001, "author": "angry", "comment": "blah angry blah angry"},
        …
        {"id": ∞ + 1, "author": "bored", "comment": "oh man, will this ever end?"},
    ]
}

قد يكون هذا هو الشكل الذي سيبدو عليه كيان النشر الذي يحتوي على تعليقات مضمنة إذا كنا نصمم مدونة نموذجية، أو نظام CMS. تكمن المشكلة في هذا المثال في أن مصفوفة التعليقات غير محدودة، ما يعني أنه لا يوجد حد (عملي) لعدد التعليقات التي يمكن أن يحتويها أي منشور واحد. قد تمثل هذه مشكلة لأن حجم العنصر يمكن أن يزداد بشكل لا نهائي، لذا يجب تجنب التصميم.

مع تزايد حجم العنصر، ستتأثر القدرة على نقل البيانات عبر السلك وقراءة العنصر وتحديثه، على نطاق واسع.

في هذه الحالة، سيكون من الأفضل مراعاة نموذج البيانات التالي.

Post item:
{
    "id": "1",
    "name": "What's new in the coolest Cloud",
    "summary": "A blog post by someone real famous",
    "recentComments": [
        {"id": 1, "author": "anon", "comment": "something useful, I'm sure"},
        {"id": 2, "author": "bob", "comment": "wisdom from the interwebs"},
        {"id": 3, "author": "jane", "comment": "....."}
    ]
}

Comment items:
[
    {"id": 4, "postId": "1", "author": "anon", "comment": "more goodness"},
    {"id": 5, "postId": "1", "author": "bob", "comment": "tails from the field"},
    ...
    {"id": 99, "postId": "1", "author": "angry", "comment": "blah angry blah angry"},
    {"id": 100, "postId": "2", "author": "anon", "comment": "yet more"},
    ...
    {"id": 199, "postId": "2", "author": "bored", "comment": "will this ever end?"}   
]

يشتمل هذا النموذج على وثيقة لكل تعليق مع خاصية تحتوي على معرف النشر. الأمر الذي يتيح أن تحتوي المنشورات على أي عدد من التعليقات ويمكن أن تزداد بفعالية. يطلب المستخدمون الذين يرغبون في رؤية مزيدٍ من أحدث التعليقات من هذه الحاوية تمرير معرف المنشور الذي يجب أن يكون مفتاح التقسيم لحاوية التعليقات.

ثمة حالة أخرى لا يكون فيها تضمين البيانات فكرة جيدة عند استخدام البيانات المضمنة في كثير من الأحيان عبر العناصر وتغييرها بشكل متكرر.

خذ هذا المقتطف JSON.

{
    "id": "1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "holdings": [
        {
            "numberHeld": 100,
            "stock": { "symbol": "zbzb", "open": 1, "high": 2, "low": 0.5 }
        },
        {
            "numberHeld": 50,
            "stock": { "symbol": "xcxc", "open": 89, "high": 93.24, "low": 88.87 }
        }
    ]
}

يمكن أن يمثل هذا محفظة الأوراق المالية للشخص. لقد اخترنا تضمين معلومات المخزون في كل مستند محفظة. في بيئة تتغير فيها البيانات ذات الصلة بشكل متكرر، مثل تطبيق تداول الأسهم، فإن تضمين البيانات التي تتغير بشكل متكرر يعني أنك تستمر في تحديث كل مستند محفظة في كل مرة يتم فيها تداول الأسهم.

يمكن تداول الأسهم zbzb عدة مئات من المرات في يوم واحد ويمكن لآلاف المستخدمين الحصول على zbzb في محفظتهم. باستخدام نموذج بيانات مثل المذكور أعلاه، سيتعين علينا تحديث عدة آلاف من مستندات الحافظة عدة مرات كل يوم مما يؤدي إلى نظام لن يتسع نطاقه بشكل جيد.

البيانات المرجعيّة

يعمل تضمين البيانات بشكل جيد في العديد من الحالات، ولكن هناك سيناريوهات يتسبب فيها إلغاء تنسيق البيانات في حدوث مشكلات أكثر ما تستحق. إذا ماذا نفعل الآن؟

قواعد البيانات الارتباطية ليست المكان الوحيد حيث يمكنك إنشاء ارتباطات بين الكيانات. في قاعدة بيانات المستندات، يمكنك الحصول على معلومات في مستند واحد يتعلق بالبيانات الموجودة في مستندات أخرى. لا نوصي بإنشاء أنظمة تكون أكثر ملاءمة لقاعدة بيانات ارتباطية في Azure Cosmos DB، أو أي قاعدة بيانات مستندات أخرى، ولكن الارتباطات البسيطة جيدة ويمكن أن تكون مفيدة.

في JSON أدناه، اخترنا استخدام مثال محفظة الأوراق المالية من وقت سابق ولكن هذه المرة نشير إلى عنصر المخزون في المحفظة بدلاً من تضمينه. بهذه الطريقة، عندما يتغير عنصر المخزون بشكل متكرر على مدار اليوم، يكون المستند الوحيد الذي يحتاج إلى التحديث هو مستند المخزون الفردي.

Person document:
{
    "id": "1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "holdings": [
        { "numberHeld":  100, "stockId": 1},
        { "numberHeld":  50, "stockId": 2}
    ]
}

Stock documents:
{
    "id": "1",
    "symbol": "zbzb",
    "open": 1,
    "high": 2,
    "low": 0.5,
    "vol": 11970000,
    "mkt-cap": 42000000,
    "pe": 5.89
},
{
    "id": "2",
    "symbol": "xcxc",
    "open": 89,
    "high": 93.24,
    "low": 88.87,
    "vol": 2970200,
    "mkt-cap": 1005000,
    "pe": 75.82
}

لكن الجانب السلبي الفوري لهذا النهج هو ما إذا كان التطبيق الخاص بك مطلوباً لإظهار معلومات حول كل سهم محتفظ به عند عرض محفظة الشخص؛ في هذه الحالة، قد تحتاج إلى القيام برحلات متعددة إلى قاعدة البيانات لتحميل المعلومات الخاصة بكل مستند مخزون. هنا اتخذنا قراراً لتحسين كفاءة عمليات الكتابة، والتي تحدث بشكل متكرر على مدار اليوم، ولكنها بدورها تتعرض للخطر في عمليات القراءة التي من المحتمل أن يكون لها تأثير أقل على أداء هذا النظام المحدد.

ملاحظة

يمكن أن تتطلب نماذج البيانات التي تمت تسويتها المزيد من الرحلات ذهاباً وإياباً إلى الخادم.

ماذا عن المفاتيح الخارجية؟

نظراً لعدم وجود مفهوم قيد أو مفتاح خارجي أو غير ذلك حاليّاً، فإن أي ارتباطات داخلية بين المستندات تجريها في المستندات تعتبر "روابط ضعيفة" بشكل فعال ولن تتحقق من صحتها قاعدة البيانات نفسها. إذا كنت تريد التأكد من أن البيانات التي يشير إليها المستند موجودة بالفعل، فأنت بحاجة إلى القيام بذلك في التطبيق الخاص بك، أو باستخدام المشغلات من جانب الخادم أو الإجراءات المخزنة في Azure Cosmos DB.

متى يتم الرجوع إليها

بشكل عام، استخدم نماذج البيانات المعيارية عندما:

  • تمثيل ارتباطات واحد لأكثر.
  • تمثيل ارتباطات كثير إلى كثير.
  • البيانات ذات الصلة تتغير بشكل متكرر.
  • يمكن أن تكون البيانات المرجعية غير محدودة.

ملاحظة

يوفر التسوية عادةً أداء كتابة أفضل.

أين أقوم بتخزين الارتباط؟

سيساعد نمو العلاقة في تحديد المستند الذي سيتم تخزين المرجع فيه.

إذا نظرنا إلى JSON أدناه، فهذه نماذج للناشرين والكتب.

Publisher document:
{
    "id": "mspress",
    "name": "Microsoft Press",
    "books": [ 1, 2, 3, ..., 100, ..., 1000]
}

Book documents:
{"id": "1", "name": "Azure Cosmos DB 101" }
{"id": "2", "name": "Azure Cosmos DB for RDBMS Users" }
{"id": "3", "name": "Taking over the world one JSON doc at a time" }
...
{"id": "100", "name": "Learn about Azure Cosmos DB" }
...
{"id": "1000", "name": "Deep Dive into Azure Cosmos DB" }

إذا كان عدد الكتب لكل ناشر صغيراً ونمواً محدوداً، فقد يكون من المفيد تخزين مرجع الكتاب داخل مستند الناشر. ومع ذلك، إذا كان عدد الكتب لكل ناشر غير محدود، فإن نموذج البيانات هذا سيؤدي إلى مصفوفات قابلة للتغيير، ومتنامية، كما في مثال مستند الناشر أعلاه.

قد يؤدي تبديل الأشياء قليلاً إلى نموذج لا يزال يمثل نفس البيانات ولكنه يتجنب الآن هذه المجموعات الكبيرة القابلة للتغيير.

Publisher document:
{
    "id": "mspress",
    "name": "Microsoft Press"
}

Book documents:
{"id": "1","name": "Azure Cosmos DB 101", "pub-id": "mspress"}
{"id": "2","name": "Azure Cosmos DB for RDBMS Users", "pub-id": "mspress"}
{"id": "3","name": "Taking over the world one JSON doc at a time", "pub-id": "mspress"}
...
{"id": "100","name": "Learn about Azure Cosmos DB", "pub-id": "mspress"}
...
{"id": "1000","name": "Deep Dive into Azure Cosmos DB", "pub-id": "mspress"}

في المثال أعلاه، قمنا بإسقاط المجموعة غير المحدودة في مستند الناشر. بدلاً من ذلك، لدينا فقط إشارة إلى الناشر في كل مستند كتاب.

كيف أقوم بنمذجة علاقات عديد إلى عديد؟

في قاعدة بيانات ارتباطية عديد إلى عديد تتم نمذجة الارتباطات غالباً باستخدام جداول ربط، والتي تقوم فقط بضم السجلات من جداول أخرى معاً.

ضم الجداول

قد تميل إلى تكرار نفس الشيء باستخدام المستندات وإنتاج نموذج بيانات مشابه لما يلي.

Author documents:
{"id": "a1", "name": "Thomas Andersen" }
{"id": "a2", "name": "William Wakefield" }

Book documents:
{"id": "b1", "name": "Azure Cosmos DB 101" }
{"id": "b2", "name": "Azure Cosmos DB for RDBMS Users" }
{"id": "b3", "name": "Taking over the world one JSON doc at a time" }
{"id": "b4", "name": "Learn about Azure Cosmos DB" }
{"id": "b5", "name": "Deep Dive into Azure Cosmos DB" }

Joining documents:
{"authorId": "a1", "bookId": "b1" }
{"authorId": "a2", "bookId": "b1" }
{"authorId": "a1", "bookId": "b2" }
{"authorId": "a1", "bookId": "b3" }

هذا من شأنه أن يعمل. ومع ذلك، فإن تحميل مؤلف مع كتبه، أو تحميل كتاب مع مؤلفه، سيتطلب دائماً استعلامين إضافيين على الأقل مقابل قاعدة البيانات. استعلام واحد إلى المستند المنضم ثم استعلام آخر لجلب المستند الفعلي الذي يتم ضمه.

إذا كان هذا الانضمام يعني لصق جزأين من البيانات معاً فقط، فلماذا لا نسقطه تماماً؟ خذ بعين الاعتبار المثال الآتي.

Author documents:
{"id": "a1", "name": "Thomas Andersen", "books": ["b1", "b2", "b3"]}
{"id": "a2", "name": "William Wakefield", "books": ["b1", "b4"]}

Book documents:
{"id": "b1", "name": "Azure Cosmos DB 101", "authors": ["a1", "a2"]}
{"id": "b2", "name": "Azure Cosmos DB for RDBMS Users", "authors": ["a1"]}
{"id": "b3", "name": "Learn about Azure Cosmos DB", "authors": ["a1"]}
{"id": "b4", "name": "Deep Dive into Azure Cosmos DB", "authors": ["a2"]}

الآن، إذا كان لدي مؤلف، فأنا أعرف فوراً الكتب التي كتبها، وعلى عكس ذلك، إذا كان لديَّ مستند كتاب تم تحميله، فسأعرف معرفات المؤلف (المؤلفين). يؤدي هذا إلى حفظ الاستعلام الوسيط مقابل جدول الانضمام مما يقلل من عدد رحلات الخادم ذهاباً وإياباً التي يتعين على التطبيق القيام بها.

نماذج البيانات الهجينة

لقد نظرنا الآن في تضمين (أو إلغاء تطبيع) البيانات والإشارة إليها (أو تطبيعها). لكل نهج إيجابيات ومساومات.

لا يجب أن يكون الأمر كذلك دائمًا، أو لا تخف من خلط الأشياء قليلاً.

استناداً إلى أنماط الاستخدام وأعباء العمل المحددة للتطبيق الخاص بك، قد تكون هناك حالات يكون فيها خلط البيانات المضمنة والمراجع منطقياً وقد يؤدي إلى منطق تطبيق أبسط مع عدد أقل من رحلات الذهاب والإياب للخادم مع الحفاظ على مستوى جيد من الأداء.

ضع في اعتبارك JSON التالي.

Author documents:
{
    "id": "a1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "countOfBooks": 3,
    "books": ["b1", "b2", "b3"],
    "images": [
        {"thumbnail": "https://....png"}
        {"profile": "https://....png"}
        {"large": "https://....png"}
    ]
},
{
    "id": "a2",
    "firstName": "William",
    "lastName": "Wakefield",
    "countOfBooks": 1,
    "books": ["b1"],
    "images": [
        {"thumbnail": "https://....png"}
    ]
}

Book documents:
{
    "id": "b1",
    "name": "Azure Cosmos DB 101",
    "authors": [
        {"id": "a1", "name": "Thomas Andersen", "thumbnailUrl": "https://....png"},
        {"id": "a2", "name": "William Wakefield", "thumbnailUrl": "https://....png"}
    ]
},
{
    "id": "b2",
    "name": "Azure Cosmos DB for RDBMS Users",
    "authors": [
        {"id": "a1", "name": "Thomas Andersen", "thumbnailUrl": "https://....png"},
    ]
}

هنا (في الغالب) اتبعنا النموذج المضمن، حيث يتم تضمين البيانات من الكيانات الأخرى في مستند المستوى الأعلى، ولكن تتم الإشارة إلى البيانات الأخرى.

إذا نظرت إلى مستند الكتاب، يمكننا أن نرى بعض الحقول المثيرة للاهتمام عندما ننظر إلى مجموعة المؤلفين. يوجد حقل id، وهو الحقل الذي نستخدمه للرجوع إلى مستند المؤلف، والممارسة القياسية في النموذج المعياري، ولكن لدينا أيضاً name وthumbnailUrl. كان من الممكن أن نكون عالقين مع idوغادرنا التطبيق للحصول على أي معلومات إضافية نحتاجها من مستند المؤلف المعني باستخدام "الرابط"، ولكن نظراً لأن تطبيقنا يعرض اسم المؤلف وصورة مصغرة مع كل كتاب معروض، يمكننا حفظ رحلة ذهاباً وإياباً إلى الخادم لكل كتاب في قائمة بإلغاء تسويةبعضالبيانات من المؤلف.

بالتأكيد، إذا تم تغيير اسم المؤلف أو أرادوا تحديث صورتهم، فسيتعين علينا تحديث كل كتاب تم نشره على الإطلاق ولكن لتطبيقنا، بناءً على افتراض أن المؤلفين لا يغيرون أسمائهم كثيراً، فهذا قرار تصميم مقبول.

في هذا المثال، توجد قيم تجميعات محسوبة مسبقاً لتوفير معالجة باهظة الثمن في عملية قراءة. في المثال، بعض البيانات المضمنة في مستند المؤلف هي بيانات يتم حسابها في وقت التشغيل. في كل مرة يتم فيها نشر كتاب جديد، يتم إنشاء مستند كتاب و يتم تعيين حقل countOfBooks على قيمة محسوبة بناءً على عدد مستندات الكتاب الموجودة لمؤلف معين. سيكون هذا التحسين جيداً في قراءة الأنظمة الثقيلة حيث يمكننا إجراء عمليات حسابية على عمليات الكتابة من أجل تحسين عمليات القراءة.

أصبحت القدرة على الحصول على نموذج بحقول محسوبة مسبقاً ممكنة لأن Azure Cosmos DB يدعم المعاملات متعددة المستندات. لا تستطيع العديد من متاجر NoSQL إجراء معاملات عبر المستندات، وبالتالي فهي تؤيد قرارات التصميم، مثل "تضمين كل شيء دائماً"، بسبب هذا القيد. باستخدام Azure Cosmos DB، يمكنك استخدام مشغلات من جانب الخادم، أو إجراءات مخزنة، تقوم بإدراج الكتب وتحديث المؤلفين، كل ذلك ضمن عملية ACID. الآن ليس لديك لتضمين كل شيء في مستند واحد فقط للتأكد من أن بياناتك لا تزال متسقة.

التمييز بين أنواع الوثائق المختلفة

في بعض السيناريوهات، قد ترغب في مزج أنواع مستندات مختلفة في نفس المجموعة؛ هذا هو الحال عادةً عندما تريد وضع العديد من المستندات ذات الصلة في نفس القسم. على سبيل المثال، يمكنك وضع كل من الكتب ومراجعات الكتب في نفس المجموعة وتقسيمها حسب bookId. في مثل هذه الحالة، تريد عادةً أن تضيف إلى مستنداتك حقلاً يحدد نوعها للتمييز بينها.

Book documents:
{
    "id": "b1",
    "name": "Azure Cosmos DB 101",
    "bookId": "b1",
    "type": "book"
}

Review documents:
{
    "id": "r1",
    "content": "This book is awesome",
    "bookId": "b1",
    "type": "review"
},
{
    "id": "r2",
    "content": "Best book ever!",
    "bookId": "b1",
    "type": "review"
}

Azure Synapse Link لـ Azure Cosmos DB هو قدرة معالجة المعاملات والتحليلات الهجينة (HTAP) الهجينة التي تمكنك من تشغيل تحليلات قريبة في الوقت الفعلي عبر البيانات التشغيلية في Azure Cosmos DB. ينشئ ارتباط Azure Synapse تكاملاً محكمًا وسلسًا بين Azure Cosmos DB وAzure Synapse Analytics.

يحدث هذا التكامل من خلال المخزن التحليلي لـ Azure Cosmos DB، وهو تمثيل عمودي لبيانات المعاملات يمكن التحليلات واسعة النطاق دون أي تأثير على أحمال عملك. هذا المخزن التحليلي مناسب للاستعلامات السريعة والاقتصادية التي تُجرى على مجموعات البيانات التشغيلية الكبيرة، دون نسخ البيانات والتأثير في أداء حمل العمليات. عند إنشاء حاوية مع تمكين مخزن تحليلي أو عند تمكين مخزن تحليلي على حاوية موجودة، تُجرى مزامنة جميع إدراجات العمليات وتحديثاتها وحذفها مع مخزن تحليلي في وقت قريب من الوقت الحقيقي، ولا يلزم وجود مهام ETL أو موجز تغيير.

باستخدام Azure Synapse Link، يمكنك الآن الاتصال مباشرة بحاويات Azure Cosmos DB من Azure Synapse Analytics والوصول إلى المخزن التحليلي دون تكلفة وحدات الطلب. يدعم Azure Synapse Analytics حاليّاً Azure Synapse Link مع Synapse Apache Spark وتجمعات SQL بلا خادم. إذا كان لديك حساب قاعدة بياناتAzure Cosmos DB عمومي، وبعد تمكينك للمخزن التحليلي لحاوية، فإنه سيكون متوفرًا في كافة مناطق هذا الحساب.

استدلال المخطط التلقائي للمخزن التحليلي

في حين يُعتبر مخزن العمليات لـ Azure Cosmos DB بيانات شبه منظمة بتنسيق الصفوف، فإن المخزن التحليلي يحتوي على تنسيق عمودي ومنظم. يُجرى هذا التحويل تلقائيًا للعملاء، باستخدام قواعد استنتاج المخطط للمخزن التحليلي. ثمة حدود في عملية التحويل: أقصى عدد للمستويات المتداخلة وأقصى لعدد للخصائص وأنواع البيانات غير المدعومة وغير ذلك المزيد.

ملاحظة

في سياق المتجر التحليلي، نعتبر البنية التالية كخاصية:

  • "عناصر" JSON أو "أزواج قيمة سلسلة مفصولة بـ : ".
  • عناصر JSON، محددة بواسطة { و}.
  • صفائف JSON، محددة بواسطة [ و].

يمكنك تقليل تأثير تحويلات استدلال المخطط وزيادة إمكانيات التحليل باستخدام الأساليب التالية.

التسوية

يصبح التنسيق بدون فائدة نظراً لأنه مع Azure Synapse Link، يمكنك الجمع بين حاوياتك باستخدام T-SQL أو Spark SQL. فيما يلي الميزات المتوقعة من التنسيق:

  • أثر بيانات أصغر في كلٍّ من المخزن التحليلي ومخزن العمليات.
  • عمليات أصغر.
  • خصائص أقل لكل مستند.
  • بنيات بيانات بمستويات متداخلة أقل.

لاحظ أن هذين العاملين الأخيرين، خصائص أقل ومستويات أقل، يساعدان في أداء الاستعلامات التحليلية ولكن يقللان أيضاً من فرص عرض أجزاء البيانات في المخزن التحليلي. كما هو موضح في المقالة المتعلقة بقواعد الاستدلال التلقائي للمخطط، ثمة حدود لعدد المستويات والخصائص المعروضة في المخزن التحليلي.

ثمة عامل آخر مهم للتنسيق، وهو أن تجمعات SQL بلا خادم في Azure Synapse تدعم مجموعات نتائج بما يصل إلى 1000 عمود، كما يُحسَب عرض الأعمدة المتداخلة ضمن هذا الحد. وبعبارة أخرى، يصل حد كلٍّ من المخزن التحليلي وتجمعات Synapse SQL بلا خادم إلى 1000 خاصية.

ولكن ما الذي يجب فعله لأن إلغاء التنسيق هو أسلوب مهم لنمذجة البيانات في Azure Cosmos DB؟ تكمن الإجابة في أنه عليك تحقيق التوازن المناسب لأحمال عملك المتعلقة بالعمليات والتحليلات.

مفتاح القسم

لا يُستخدَم مفتاح قسم Azure Cosmos DB (PK) في المخزن التحليلي. ويمكنك الآن استخدام تقسيم مخصص للمخزن التحليلي لنُسخ من المخزن التحليلي باستخدام أي مفتاح قسم تريده. وبسبب عملية العزل هذه، يمكنك اختيار مفتاح قسم لبيانات العملية مع التركيز على استيعاب البيانات وقراءات النقطة، بينما يمكن إجراء استعلامات التقسيم المشترك باستخدام Azure Synapse Link. لنعرض مثالاً:

في سيناريو إنترنت الأشياء العالمي الافتراضي، يكون device id مفتاح قسم جيداً لأن جميع الأجهزة لديها حجم بيانات مماثل ومع ذلك لن يكون لديك مشكلة قسم حرجة. ولكن إذا كنت ترغب في تحليل بيانات أكثر من جهاز واحد، مثل "جميع البيانات من أمس" أو "الإجماليات لكل مدينة"، فقد تواجه مشكلات لأنها تمثل استعلامات التقسيم المشترك. يمكن أن تضر هذه الاستعلامات بأداء العمليات لأنها تستخدم جزءاً من معدل النقل في تشغيل وحدات الطلب. لكن مع Azure Synapse Link، يمكنك تشغيل هذه الاستعلامات التحليلية دون تكاليف وحدات الطلب. يُحسَن التنسيق العمودي للمخزن التحليلي للاستعلامات التحليلية ويطبق Azure Synapse Link هذه الخاصية للسماح بأداء رائع مع أوقات تشغيل Azure Synapse Analytics.

أنواع البيانات وأسماء الخصائص

توضح مقالة قواعد الاستدلال التلقائي للمخطط أنواع البيانات المعتمدة. بينما يمنع نوع البيانات غير المدعوم عملية العرض في المخزن التحليلي، قد تُعالَج أنواع البيانات المعتمدة بشكل مختلف عن طريق أوقات تشغيل Azure Synapse. مثال واحد: عند استخدام سلاسل التاريخ والوقت التي تتبع معيار التوقيت العالمي المتفق عليه ISO 8601، ستعرض تجمعات Spark في Azure Synapse هذه الأعمدة كسلسلة وتعرض تجمعات SQL بلا خادم في Azure Synapse هذه الأعمدة بتنسيق varchar(8000).

يتمثل تحدٍّ آخر في عدم قبول Azure Synapse Spark جميع الأحرف. في حين تُقبَل المسافات البيضاء، لا تُقبَل أحرف مثل علامة النقطتين والعلامة النطقية جراف والفاصلة. لنفترض أن المستند يحتوي على خاصية باسم "الاسم الأول، واسم العائلة". ستُعرَض هذه الخاصية في مخزن تحليلي وتتمكن تجمعات Synapse SQL بلا خادم من قراءتها دون مشكلة. ولكن نظراً لأنها في متجر تحليلي، لا يمكن أن يقرأ Azure Synapse Spark أي بيانات من متجر تحليلي، بما في ذلك جميع الخصائص الأخرى. في النهاية، لا يمكنك استخدام Azure Synapse Spark عندما يكون لديك خاصية واحدة تتضمن أحرفاً غير مدعومة في أسمائهم.

تبسيط البيانات

سيتم تمثيل جميع الخصائص في المستوى الجذر لبيانات Azure Cosmos DB في المخزن التحليلي كعمود وسيتم تمثيل كل شيء آخر موجود في مستويات أعمق من نموذج بيانات المستند الخاص بك ك JSON، أيضا في الهياكل المتداخلة. تتطلب البنيات المتداخلة معالجة إضافية من أوقات تشغيل Azure Synapse لتبسيط البيانات بتنسيق منظم، وقد يكون هذا الأمر صعباً في سيناريوهات البيانات الضخمة.

سيحتوي المستند أدناه على عمودين في المخزن التحليلي فقط، id وcontactDetails. تتطلب جميع البيانات الأخرى email وphone معالجة إضافية من خلال وظائف SQL لقراءتها بشكل فردي.


{
    "id": "1",
    "contactDetails": [
        {"email": "thomas@andersen.com"},
        {"phone": "+1 555 555-5555"}
    ]
}

يحتوي المستند أدناه على ثلاثة أعمدة في المخزن التحليلي وid وemail وphone. يمكن الوصول إلى جميع البيانات مباشرة بتنسيق الأعمدة.


{
    "id": "1",
    "email": "thomas@andersen.com",
    "phone": "+1 555 555-5555"
}

تكوين الطبقات المسؤولة عن البيانات

يسمح لك Azure Synapse Link بتقليل التكاليف من المنظورات التالية:

  • عدد أقل من الاستعلامات قيد التشغيل في قاعدة بيانات العملية.
  • مفتاح قسم مُحسَّن لاستيعاب البيانات وقراءات النقطة والحد من أثر البيانات وسيناريوهات التقسيم الحادة وتقسيمات الأقسام.
  • تراتب البيانات نظرًا لأن وقت البقاء التحليلي(attl) مستقل عن مدة بقاء المعاملات (tttl). يمكنك الاحتفاظ ببيانات العملية في مخزن العمليات لبضعة أيام أو أسابيع أو أشهر والاحتفاظ بالبيانات في المخزن التحليلي لسنوات أو إلى الأبد. يجمع التنسيق العمودي للمخزن التحليلي ضغط البيانات الطبيعي من 50٪ إلى 90٪. وتمثل تكلفتها لكل جيجابايت حوالي 10 ٪ من السعر الفعلي لمخزن العمليات. لمزيد من المعلومات بشأن قيود النسخ الاحتياطي الحالية، انظر نظرة عامة تحليلية على المتجر.
  • لا توجد وظائف ETL قيد التشغيل في بيئتك، مما يعني أنك لست بحاجة إلى توفير وحدات طلب لها.

التكرار المُتحكَّم به

إنه خيار بديل مميز للحالات التي يكون فيها نموذج البيانات موجوداً بالفعل ولا يمكن تغييره. ولا يتناسب نموذج البيانات الحالي مع المخزن التحليلي جيداً بسبب قواعد الاستدلال التلقائي للمخطط مثل حد المستويات المتداخلة أو أقصى عدد للخصائص. إذا كانت هذه هي حالتك، يمكنك استخدام موجز تغيير Azure Cosmos DB لنسخ نسخة مماثلة من بياناتك في حاوية أخرى، وتطبيق التحويلات المطلوبة لنموذج بيانات سهل الاستخدام لـ Azure Synapse Link. لنعرض مثالاً:

السيناريو

تُستخدَم الحاوية CustomersOrdersAndItems لتخزين الطلبات عبر الإنترنت بما فيها تفاصيل العميل والعناصر: عنوان الفاتورة وعنوان التسليم وطريقة التسليم وحالة التسليم وسعر العناصر وما إلى ذلك. تُعرَض أول 1000 خاصية فقط ولا تُدرَج المعلومات الرئيسية في المخزن التحليلي، ما يؤدي إلى منع استخدام Azure Synapse Link. تحتوي الحاوية على وحدات بيتابايت (PB) من السجلات، لا يمكن تغيير تطبيقها وإعادة نمذجة البيانات.

يتمثل منظور آخر للمشكلة في حجم البيانات الضخمة. يستخدم قسم التحليلات مليارات الصفوف باستمرار، ما يمنعها من استخدام tttl لحذف البيانات القديمة. إن الحفاظ على سجل البيانات بأكمله في قاعدة بيانات العملية بسبب الاحتياجات التحليلية يجبرها على زيادة توفير وحدات الطلب باستمرار، مما يؤثر في التكاليف. تتنافس أحمال العمل للعمليات والتحليلات على الموارد نفسها في الوقت نفسه.

ما الذي يجب فعله؟

الحل الذي يحتوي على موجز التغيير

  • قرر الفريق الهندسي استخدام موجز التغيير لملء ثلاث حاويات جديدة: Customers وOrders وItems. باستخدام موجز التغيير، يتمكنون من تنسيق البيانات وتبسيطها. تُزال المعلومات غير الضرورية من نموذج البيانات وتحتوي كل حاوية على ما يقرب من 100 خاصية، مما يؤدي إلى تجنب فقدان البيانات بسبب حدود الاستدلال التلقائي للمخطط.
  • تتضمن هذه الحاويات الجديدة مخزناً تحليليّاً ممكناً ويستخدم قسم التحليلات الآن Synapse Analytics لقراءة البيانات والحد من استخدام وحدات الطلب لأن الاستفسارات التحليلية تُجرى في Synapse Apache Spark وتجمعات SQL بلا خادم.
  • تحتوي الحاوية CustomersOrdersAndItems الآن على مجموعة tttl للحفاظ على البيانات لمدة ستة أشهر فقط، ما يسمح بخفض آخر في استخدام وحدات الطلب، لأن هناك ما لا يقل عن 10 وحدات طلب لكل جيجابايت في Azure Cosmos DB. بيانات أقل، وحدات طلب أقل.

التعاليم الرئيسية

أهم المزايا الواردة في هذه المقالة هي فهم أن نمذجة البيانات في عالم خال من المخططات لا تقل أهمية عن أي وقت مضى.

مثلما لا توجد طريقة واحدة لعرض جزء من البيانات على الشاشة، لا توجد طريقة واحدة لنمذجة بياناتك. أنت بحاجة إلى فهم طلبك وكيفية إنتاج البيانات واستهلاكها ومعالجتها. بعد ذلك، من خلال تطبيق بعض الإرشادات المقدمة هنا، يمكنك تحديد إنشاء نموذج يلبي الاحتياجات الفورية لتطبيقك. عندما تحتاج تطبيقاتك إلى التغيير، يمكنك الاستفادة من مرونة أي قاعدة بيانات خالية من المخططات لاحتواء هذا التغيير وتطوير نموذج البيانات الخاص بك بسهولة.

الخطوات التالية