تصميم البيانات في 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"}
    ]
}

سيكون للمستند ثلاثة أعمدة في المخزن التحليلي و idemailو و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 بلا خادم.
  • تم الآن تعيين tttl للحاوية CustomersOrdersAndItems للاحتفاظ بالبيانات لمدة ستة أشهر فقط، ما يسمح بتخفيض استخدام وحدات الطلب الأخرى، حيث يوجد حد أدنى لوحدة طلب واحدة لكل جيجابايت في Azure Cosmos DB. بيانات أقل، وحدات طلب أقل.

النقاط الرئيسية

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

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