أنماط تصميم الجدول

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

to look up related data

تبين خريطة النمط أعلاه بعض العلاقات بين الأنماط (الأزرق) والأنماط المضادة (البرتقالية) الموثقة في هذا الدليل. يوجد العديد من الأنماط الأخرى التي تستحق الدراسة. على سبيل المثال، أحد السيناريوهات الرئيسية لخدمة الجدول هو استخدام ⁧⁩ نمط العرض الفعلي ⁧⁩ من نمط ⁧⁩ فصل مسؤولية استعلام الأوامر (CQRS) ⁧⁩.

نمط الفهرس الثانوي الموجود داخل القسم

قم بتخزين نسخ متعددة من كل كيان باستخدام قيم ⁧⁩ RowKey ⁧⁩ مختلفة (في نفس القسم) لتمكين عمليات البحث السريعة والفعالة وترتيبات الفرز البديلة باستخدام قيم ⁧⁩ RowKey ⁧⁩ مختلفة. يمكن الاحتفاظ بالتحديثات بين النسخ متسقة باستخدام حركات مجموعة الكيانات (EGTs).

السياق والمشكلة

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

Graphic of employee entity where a client application can use a point query to retrieve an individual employee entity by using the department name and the employee ID (the PartitionKey and RowKey values).

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

حل

للتغلب على نقص الفهارس الثانوية، يمكنك تخزين نسخ متعددة من كل كيان مع كل نسخة باستخدام قيمة ⁧⁩ RowKey ⁧⁩ مختلفة. إذا قمت بتخزين كيان مع الهياكل الموضحة أدناه، فإنه يمكنك استرداد كيانات الموظفين بكفاءة بناءً على عنوان البريد الإلكتروني أو معرّف الموظف. تمكنك قيم البادئة لـ ⁧⁩ RowKey ⁧⁩ و"empid_" و"email_" من الاستعلام عن موظف واحد أو مجموعة من الموظفين باستخدام مجموعة من عناوين البريد الإلكتروني أو معرفات الموظفين.

Graphic showing employee entity with varying RowKey values

يحدد معيارا التصفية التاليان (أحدهما يبحث عن طريق معرف الموظف والآخر يبحث عن طريق عنوان البريد الإلكتروني) كلاهما استعلامات نقطية:

  • مرشح $ = (PartitionKey eq 'Sales') و(RowKey eq 'empid_000223')
  • مرشح $ = (PartitionKey eq 'Sales') و(RowKey eq '⁧email_jonesj@contoso.com⁩')

إذا قمت بالاستعلام عن مجموعة من كيانات الموظفين، فإنه يمكنك تحديد نطاق تم فرزه بترتيب معرّف الموظف، أو نطاق تم فرزه بترتيب عنوان البريد الإلكتروني عن طريق الاستعلام عن الكيانات ذات البادئة المناسبة في ⁧⁩ RowKey ⁧⁩.

  • للعثور على جميع الموظفين في قسم المبيعات بمعرف موظف في النطاق 000100 إلى 000199، استخدم: مرشح $ = (PartitionKey eq 'Sales') و(RowKey ge 'empid_000100') و(RowKey le 'empid_000199')

  • للعثور على جميع الموظفين في قسم المبيعات بعنوان بريد إلكتروني يبدأ بالحرف "أ" استخدم: مرشح $ = (PartitionKey eq 'Sales') و(RowKey ge 'email_a') و(RowKey lt 'email_b')

    إن بنية المرشح المستخدمة في الأمثلة أعلاه مأخوذة من خدمة الجدول REST API، لمزيد من المعلومات، راجع ⁧⁩ كيانات الاستعلام ⁧⁩.

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

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

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

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

  • يجب أن تكون القيمة المستخدمة لـ ⁧⁩ RowKey ⁧⁩ فريدة لكل كيان. ضع في اعتبارك استخدام قيم المفاتيح المركبة.

  • يتيح وضع القيم الرقمية في ⁧⁩ RowKey ⁧⁩ (على سبيل المثال، معرف الموظف 000223) إمكانية الفرز والتصفية الصحيحين استنادًا إلى الحدود العليا والسفلى.

  • لا تحتاج بالضرورة إلى تكرار كافة خصائص الكيان الخاص بك. على سبيل المثال، إذا كانت الاستعلامات التي تبحث عن الكيانات باستخدام عنوان البريد الإلكتروني في ⁧⁩ RowKey ⁧⁩ لا تحتاج أبدًا إلى عمر الموظف، فقد يكون لهذه الكيانات الهيكل التالي:

    Graphic of employee entity

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

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط الفهرس الثانوي بين الأقسام

قم بتخزين نسخ متعددة من كل كيان باستخدام قيم ⁧⁩ RowKey ⁧⁩ مختلفة في أقسام منفصلة أو في جداول منفصلة لتمكين عمليات البحث السريعة والفعالة وترتيبات الفرز البديلة باستخدام قيم ⁧⁩ RowKey ⁧⁩ مختلفة.

السياق والمشكلة

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

Graphic of employee entity structure that, when used, a client application can use a point query to retrieve an individual employee entity by using the department name and the employee ID (the PartitionKey and RowKey values).

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

تتوقع حجمًا كبيرًا من العمليات ضد هذه الكيانات وتريد تقليل مخاطر خدمة الجدول إلى الحد من عميلك.

حل

للتغلب على نقص الفهارس الثانوية، يمكنك تخزين نسخ متعددة من كل كيان مع كل نسخة باستخدام قيم ⁧⁩ PartitionKey ⁧⁩ و⁧⁩ RowKey ⁧⁩ مختلفة. إذا قمت بتخزين كيان مع الهياكل الموضحة أدناه، فإنه يمكنك استرداد كيانات الموظفين بكفاءة بناءً على عنوان البريد الإلكتروني أو معرّف الموظف. تمكّنك قيم البادئة ⁧⁩ PartitionKey ⁧⁩ و"empid_" و"email_" من تحديد الفهرس الذي تريد استخدامه للاستعلام.

Graphic showing employee entity with primary index and employee entity with secondary index

يحدد معيارا التصفية التاليان (أحدهما يبحث عن طريق معرف الموظف والآخر يبحث عن طريق عنوان البريد الإلكتروني) كلاهما استعلامات نقطية:

  • مرشح $ = (PartitionKey eq 'empid_Sales') و(RowKey eq '000223')
  • مرشح $ = (PartitionKey eq 'email_Sales') و(RowKey eq '⁧jonesj@contoso.com⁩')

إذا قمت بالاستعلام عن مجموعة من كيانات الموظفين، فإنه يمكنك تحديد نطاق تم فرزه بترتيب معرّف الموظف، أو نطاق تم فرزه بترتيب عنوان البريد الإلكتروني عن طريق الاستعلام عن الكيانات ذات البادئة المناسبة في ⁧⁩ RowKey ⁧⁩.

  • للعثور على جميع الموظفين في قسم المبيعات الذين لديهم معرف موظف في النطاق ⁧⁩ 000100 ⁧⁩ إلى ⁧⁩ 000199 ⁧⁩ تم فرزهم في استخدام أمر معرّف الموظف: مرشح $ = (PartitionKey eq 'empid_Sales') و( RowKey ge '000100') و(RowKey le '000199')
  • للعثور على جميع الموظفين في قسم المبيعات بعنوان بريد إلكتروني يبدأ بـ "أ" تم فرزها في طلب عنوان البريد الإلكتروني، استخدم: مرشح $ = (PartitionKey eq 'email_Sales') و(RowKey ge 'a') و(RowKey lt 'b ")

إن بنية المرشح المستخدمة في الأمثلة أعلاه مأخوذة من خدمة الجدول REST API، لمزيد من المعلومات، راجع ⁧⁩ كيانات الاستعلام ⁧⁩.

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • يمكنك الحفاظ على تناسق الكيانات المكررة مع بعضها البعض في نهاية المطاف باستخدام ⁧⁩ نمط المعاملات المتسق في نهاية المطاف ⁧⁩ للحفاظ على كيانات الفهرس الأساسية والثانوية.

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

  • يجب أن تكون القيمة المستخدمة لـ ⁧⁩ RowKey ⁧⁩ فريدة لكل كيان. ضع في اعتبارك استخدام قيم المفاتيح المركبة.

  • يتيح وضع القيم الرقمية في ⁧⁩ RowKey ⁧⁩ (على سبيل المثال، معرف الموظف 000223) إمكانية الفرز والتصفية الصحيحين استنادًا إلى الحدود العليا والسفلى.

  • لا تحتاج بالضرورة إلى تكرار كافة خصائص الكيان الخاص بك. على سبيل المثال، إذا كانت الاستعلامات التي تبحث عن الكيانات باستخدام عنوان البريد الإلكتروني في ⁧⁩ RowKey ⁧⁩ لا تحتاج أبدًا إلى عمر الموظف، فقد يكون لهذه الكيانات الهيكل التالي:

    Graphic showing employee entity with secondary index

  • يفضل عادة تخزين البيانات المكررة والتأكد من أنه يمكنك استرداد جميع البيانات التي تحتاجها باستخدام استعلام واحد بدلاً من استخدام استعلام واحد لتحديد موقع كيان باستخدام الفهرس الثانوي وآخر للبحث عن البيانات المطلوبة في الفهرس الأساسي.

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط عمليات متسق في نهاية المطاف

قم بتمكين السلوك المتسق عبر حدود الأقسام أو حدود نظام التخزين باستخدام قوائم انتظار Azure.

السياق والمشكلة

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

  • الكيانات المخزنة في قسمين مختلفين في الجدول نفسه أو في جداول مختلفة أو في حسابات تخزين مختلفة.
  • كيان مخزن في خدمة الجدول وكيان ثنائي كبير الحجم مخزن في خدمة Blob.
  • كيان مخزن في خدمة Table وملف في نظام ملفات.
  • كيان مخزن في خدمة Table تمت فهرسته بعد باستخدام خدمة البحث Azure المعرفي.

حل

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

Solution diagram for eventual consistency

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

في هذا المثال، تُدرج الخطوة 4 الموظف في جدول ⁧⁩ أرشيف ⁧⁩. يمكن أن تضيف الموظف إلى كائن ثنائي كبير الحجم في خدمة Blob أو ملف في نظام الملفات.

حالات الاسترداد من حالات الفشل

من المهم أن تكون العمليات في الخطوتين ⁧⁩ 4 ⁧⁩ و⁧⁩ 5 ⁧⁩ ⁧⁩ غير فعالة ⁧⁩ في حالة احتياج دور العامل إلى إعادة تشغيل عملية الأرشفة. إذا كنت تستخدم خدمة الجدول، في الخطوة ⁧⁩ 4 ⁧⁩ يجب عليك استخدام عملية "إدراج أو استبدال"؛ للخطوة ⁧⁩ 5 ⁧⁩ يجب عليك استخدام عملية "الحذف إن وجد" في مكتبة العميل التي تستخدمها. إذا كنت تستخدم نظام تخزين آخر، فإنه يجب عليك استخدام عملية فعالة مناسبة.

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

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

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • لا يوفر هذا الحل لعزل العمليات. على سبيل المثال، يمكن للعميل قراءة الجدولين ⁧⁩ الحالي ⁧⁩ و⁧⁩ الأرشيف ⁧⁩ عندما يكون دور العامل بين الخطوتين ⁧⁩ 4 ⁧⁩ و⁧⁩ 5 ⁧⁩، ورؤية عرض غير متناسق للبيانات. ستكون البيانات متسقة في نهاية الأمر.
  • يجب أن تكون على يقين من أن الخطوتين 4 و5 غير فاعليتين من أجل ضمان الاتساق في نهاية المطاف.
  • يمكنك قياس الحل باستخدام قوائم انتظار متعددة ومثيلات دور العامل.

موعد استخدام النمط

استخدم هذا النمط عندما تريد ضمان التناسق النهائي بين الكيانات الموجودة في أقسام أو جداول مختلفة. بمقدورك توسيع هذا النمط لضمان الاتساق النهائي للعمليات عبر خدمة Table وخدمة Blob ومصادر بيانات التخزين الأخرى غير Azure مثل قاعدة البيانات أو نظام الملفات.

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

ملاحظة

إذا كان عزل العمليات مهمًا لحلك، فإنه يجب أن تفكر في إعادة تصميم الجداول لتمكينك من استخدام EGTs.

نمط كيانات الفهارس

الإبقاء على كيانات الفهرس لتمكين عمليات البحث الفعالة التي تعرض قوائم الكيانات.

السياق والمشكلة

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

Graphic of employee entity structure where a client application can efficiently retrieve an individual employee entity by using the department name and the employee ID (the PartitionKey and RowKey).

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

حل

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

  • استعمل تخزين كائن ثنائي كبير الحجم.
  • إنشاء كيانات فهرس في نفس القسم، مثل كيانات الموظفين.
  • قم بإنشاء كيانات فهرس في قسم أو جدول منفصل.

⁩خيار رقم 1: استخدام تخزين كيان ثنائي كبير الحجم⁧

بالنسبة إلى الخيار الأول، يمكنك إنشاء blob لكل اسم عائلة فريد، وفي كل متجر blob قائمة بقيم ⁧⁩ PartitionKey ⁧⁩ (القسم) و⁧⁩ RowKey ⁧⁩ (معرّف الموظف) للموظفين الذين هذا الاسم الأخير. عند إضافة موظف أو حذفه، يجب عليك التأكد من أن محتوى البيانات الثنائية الكبيرة ذات الصلة يتوافق في النهاية مع كيانات الموظفين.

⁩خيار رقم 2:⁧⁩ إنشاء كيانات فهرس في نفس القسم

بالنسبة إلى الخيار الثاني، استخدم كيانات الفهرس التي تخزن البيانات المذكورة أدناه:

Graphic showing employee entity, with string containing a list of employee IDs with same last name

تشمل الخاصية ⁧⁩EmployeeIDs⁧⁩ على قائمة بمعرفات الموظفين للموظفين الذين تم تخزين الاسم الأخير لهم في ⁧⁩RowKey⁧⁩.

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

  1. استرد كيان الفهرس بقيمة ⁧⁩ PartitionKey ⁧⁩ "المبيعات" وقيمة ⁧⁩ RowKey ⁧⁩ "جونز". احفظ ETag لهذا الكيان لاستخدامه في الخطوة 2.
  2. أنشئ معاملة مجموعة كيان (أي عملية مجمعة) تُدرج كيان الموظف الجديد (قيمة ⁧⁩ PartitionKey ⁧⁩ "المبيعات" و⁧⁩ RowKey ⁧⁩ القيمة "000152")، وتقوم بتحديث كيان الفهرس (⁧⁩ PartitionKey ⁧⁩ قيمة "المبيعات" و⁧⁩ RowKey ⁧⁩ القيمة "جونز") عن طريق إضافة معرف الموظف الجديد إلى القائمة في الحقل "معرفات الموظفين". لمزيد من المعلومات بشأن عمليات مجموعة الكيانات، راجع معاملات مجموعة الكيانات.
  3. إن فشلت عملية مجموعة الكيانات بسبب خطأ التزام متفائل (قام شخص آخر بتعديل كيان الفهرس للتو)، فأنت بحاجة إلى البدء من جديد في الخطوة 1 مرة أخرى.

بمقدورك استخدام نهج مماثل لحذف موظف إذا كنت تستخدم الخيار الثاني. يعتبر تغيير الاسم الأخير للموظف أكثر تعقيدًا قليلاً لأنك ستحتاج إلى تنفيذ معاملة مجموعة كيان تقوم بتحديث ثلاثة كيانات: كيان الموظف وكيان الفهرس للاسم الأخير القديم وكيان الفهرس للاسم الأخير الجديد. ينبغي لك استرداد كل كيان قبل إجراء أي تغييرات لاسترداد قيم ETag التي يمكنك استخدامها بعد ذلك لإجراء التحديثات باستخدام التزامن المتفائل.

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

  1. استرجع كيان الفهرس بقيمة ⁧⁩ PartitionKey ⁧⁩ "المبيعات" وقيمة ⁧⁩ RowKey ⁧⁩ "جونز".
  2. وزّع قائمة معرفات الموظفين في الحقل معرفات الموظفين.
  3. إذا كنت بحاجة إلى معلومات إضافية حول كل من هؤلاء الموظفين (مثل عناوين البريد الإلكتروني الخاصة بهم)، فاسترد كل كيان من كيانات الموظفين باستخدام قيم ⁧⁩ PartitionKey ⁧⁩ قيمة "المبيعات" و⁧⁩ RowKey ⁧⁩ من قائمة الموظفين التي حصلت عليها في الخطوة 2.

⁩خيار رقم 3:⁧⁩ إنشاء كيانات فهرس في قسم أو جدول منفصل

بالنسبة إلى الخيار الثالث، استعمل كيانات الفهرس التي تخزن البيانات التالية:

Screenshot that shows the Employee index entity that contains a list of employee IDs for employees with the last name stored in the RowKey and PartitionKey.

تحتوي خاصية ⁧⁩EmployeeDetails⁧⁩ على قائمة بمعرفات الموظفين وأزواج أسماء الأقسام للموظفين مع الاسم الأخير المخزن في ⁧RowKey⁩.

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

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • يحتاج هذا الحل استعلامين على الأقل لاسترداد الكيانات المطابقة: أحدهما للاستعلام عن كيانات الفهرس للحصول على قائمة قيم ⁧⁩RowKey⁧⁩، ثم الاستعلامات لاسترداد كل كيان في القائمة.
  • بالرجوع إلى حجم الكيان الفردي يبلغ 1 ميغابايت كحد أقصى، يفترض الخيار رقم 2 والخيار رقم 3 في الحل أن قائمة معرفات الموظفين لأي اسم عائلة معين لا تزيد أبدًا عن 1 ميغابايت. إذا كان من المحتمل أن يزيد حجم قائمة معرفات الموظفين عن 1 ميغابايت، فاستخدم الخيار رقم 1 وقم بتخزين بيانات الفهرس في تخزين كائن ثنائي كبير الحجم.
  • في حالة استخدام الخيار رقم 2 (استخدام فريق الخبراء المتخصصين للتعامل مع إضافة الموظفين وحذفهم، وتغيير الاسم الأخير للموظف)، فإنه يجب عليك تقييم ما إذا كان حجم المعاملات سيقترب من حدود قابلية التوسع في قسم معين. إذا كانت هذه هي الحالة، يجب أن تفكر في حل متسق في النهاية (الخيار رقم 1 أو الخيار رقم 3) يستخدم قوائم الانتظار للتعامل مع طلبات التحديث ويمكّنك من تخزين كيانات الفهرس في قسم منفصل عن كيانات الموظفين.
  • يفترض الخيار رقم 2 في هذا الحل أنك تريد البحث عن طريق الاسم الأخير داخل القسم: على سبيل المثال، تريد استرداد قائمة بالموظفين باسم العائلة "جونز" في قسم المبيعات. إذا كنت تريد أن تكون قادرًا على البحث عن جميع الموظفين الذين يحملون اسمًا أخيرًا جونز عبر المؤسسة بأكملها، فاستخدم إما الخيار رقم 1 أو الخيار رقم 3.
  • يمكنك تنفيذ حل قائم على قائمة الانتظار يوفر تناسقًا نهائيًا (راجع ⁧⁩ نمط العمليات المتسق في النهاية ⁧⁩ للحصول على مزيد من التفاصيل).

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط التخلص من التطبيع

اجمع البيانات ذات الصلة معًا في كيان واحد لتمكينك من استرداد جميع البيانات التي تحتاجها باستخدام استعلام نقطي واحد.

السياق والمشكلة

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

Graphic of department entity and employee entity

حل

عوضًا من تخزين البيانات في كيانين منفصلين، قم بإلغاء تطبيع البيانات والاحتفاظ بنسخة من تفاصيل المدير في كيان القسم. على سبيل المثال:

Graphic of denormalized and combined department entity

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

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

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

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط المفتاح المركب

استخدم قيم ⁧⁩ RowKey ⁧⁩ المركبة لتمكين العميل من البحث عن البيانات ذات الصلة باستخدام استعلام نقطة واحدة.

السياق والمشكلة

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

افترض أنك تقوم بتخزين كيانات الموظفين في خدمة Table باستخدام البنية التالية:

Graphic of employee entity structure you should use to store employee entities in Table storage.

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

Graphic of employee review entity

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

حل

قم بتخزين نوع كيان جديد في جدولك الأصلي باستخدام كيانات بالبنية التالية:

Graphic of employee entity with compound key

لاحظ كيف أن ⁧⁩ RowKey ⁧⁩ صار الآن مفتاحًا مركبًا يتكون من معرف الموظف وسنة بيانات المراجعة التي تمكنك من استرداد أداء الموظف ومراجعة البيانات مع طلب واحد لكيان واحد.

يبين المثال التالي كيفية استرداد جميع بيانات المراجعة لموظف معين (مثل 000123 الموظفين في قسم المبيعات):

مرشح $ = (PartitionKey eq 'Sales') و(RowKey ge 'empid_000123') و(RowKey lt '000123_2012') ⁧&⁩ $ select = RowKey، تقييم المدير، تقييم الأقران، التعليقات

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • ينبغي لك استخدام حرف فاصل مناسب يجعل من السهل تحليل قيمة ⁧⁩RowKey⁧⁩ : على سبيل المثال، ⁧⁩000123_2012⁧⁩.
  • تقوم أيضًا بتخزين هذا الكيان في نفس القسم مثل الكيانات الأخرى التي تحتوي على بيانات ذات صلة لنفس الموظف، ما يعني أنه يمكنك استخدام EGTs للحفاظ على اتساق قوي.
  • عليك التفكير في عدد المرات التي ستقوم فيها بالاستعلام عن البيانات لتحديد ما إذا كان هذا النمط مناسبا أم لا. على سبيل المثال، إن كنت ستصل إلى بيانات المراجعة بصفة متكررة وبيانات الموظف الرئيسية في كثير من الأحيان، فإنه يجب عليك الاحتفاظ بها ككيانات منفصلة.

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط ذيل السجلات

استرد الكيانات ⁧⁩ n ⁧⁩ التي تمت إضافتها مؤخرًا إلى القسم باستخدام قيمة ⁧⁩ RowKey ⁧⁩ التي تفرز في ترتيب التاريخ والوقت العكسي.

السياق والمشكلة

كان أحد المتطلبات المشتركة قادرًا على استرداد الكيانات التي تم إنشاؤها مؤخرًا، على سبيل المثال، أحدث 10 مطالبات بالمصروفات قدمها الموظف. تدعم استعلامات الجدول عملية استعلام ⁧⁩ $ top ⁧⁩ لإرجاع الكيانات ⁧⁩ n ⁧⁩ الأولى من مجموعة: لا توجد عملية استعلام مكافئة لإرجاع آخر n كيانات في مجموعة.

حل

قم بتخزين الكيانات باستخدام ⁧⁩ RowKey ⁧⁩ الذي يفرز بشكل طبيعي بترتيب التاريخ / الوقت العكسي باستخدام بحيث يكون الإدخال الأحدث دائمًا هو الأول في الجدول.

على سبيل المثال، لتكون قادرُا على استرداد أحدث 10 مطالبات نفقات قدمها موظف، يمكنك استخدام قيمة علامة عكسية مشتقة من التاريخ/الوقت الحالي. يوضح نموذج التعليمة البرمجية C # التالي طريقة واحدة لإنشاء قيمة "علامات مقلوبة" مناسبة لـ ⁧⁩ RowKey ⁧⁩ التي تفرز من الأحدث إلى الأقدم:

string invertedTicks = string.Format("{0:D19}", DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks);

بمقدورك العودة إلى قيمة التاريخ والوقت باستخدام التعليمة البرمجية التالية:

DateTime dt = new DateTime(DateTime.MaxValue.Ticks - Int64.Parse(invertedTicks));

يبدو استعلام الجدول على نحو ما يلي:

https://myaccount.table.core.windows.net/EmployeeExpense(PartitionKey='empid')?$top=10

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

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

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط حذف حجم كبير

تمكين حذف حجم كبير من الكيانات عن طريق تخزين جميع الكيانات للحذف المتزامن في جدول منفصل خاص بها؛ حذف الكيانات عن طريق حذف الجدول.

السياق والمشكلة

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

أحد التصميمات الممكنة هو استخدام تاريخ ووقت طلب تسجيل الدخول الموجودة في⁧⁩RowKey⁧⁩:

Graphic of login attempt entity

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

حل

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

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

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

موعد استخدام النمط

استعمل هذا النمط عندما يكون لديك عدد كبير من الكيانات التي يجب حذفها في نفس الوقت.

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

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

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

السياق والمشكلة

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

Graphic of message stats entity

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

حل

استخدم التصميم التالي باستخدام خاصية منفصلة لتخزين عدد الرسائل لكل ساعة:

Graphic showing message stats entity with separated properties

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

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • في حالة دعم تناسب سلسلة البيانات الكاملة مع كيان واحد (يمكن أن يحتوي الكيان على ما يصل إلى 252 خاصية)، فاستخدم مخزن بيانات بديلاً مثل نقطة.
  • في حالة امتلاكك العديد من العملاء الذين يقومون بتحديث كيان في وقت واحد، فستحتاج إلى استخدام ⁧⁩ETag⁧⁩ لتنفيذ تزامن متفائل. إذا كان لديك العديد من العملاء، فقد تواجه منافسة عالية.

موعد استخدام النمط

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط كيانات واسعة

استخدم كيانات حقيقية متعددة لتخزين الكيانات المنطقية التي تحتوي على أكثر من 252 خاصية.

السياق والمشكلة

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

حل

باستخدام خدمة Table، يمكنك تخزين كيانات متعددة لتمثيل عنصر أعمال كبير واحد يحتوي على أكثر من 252 خاصية. على سبيل المثال، إن رغبت في تخزين عدد رسائل المراسلة الفورية التي أرسلها كل موظف خلال آخر 365 يومًا، فإنه يمكنك استخدام التصميم التالي الذي يستخدم كيانين بمخططات مختلفة:

Graphic showing message stats entity with Rowkey 01 and message stats entity with Rowkey 02

في حالة الحاجة إلى إجراء تغيير يتطلب تحديث كلا الكيانين للحفاظ على مزامنتهما مع بعضهما، فإنه يمكنك استخدام EGT. وإلا، يمكنك استعمال عملية دمج واحدة لتحديث عدد الرسائل ليوم معين. لاسترداد جميع البيانات الخاصة بموظف واحد، يجب عليك استرداد كلا الكيانين، والذي يمكنك القيام به باستخدام طلبين فعالين يستخدمان كلا من ⁧⁩قيمة PartitionKey⁧⁩ و⁧⁩RowKey⁧⁩ .

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • يتضمن استرداد كيان منطقي كامل عمليتي تخزين على الأقل: واحدة لاسترداد كل كيان فعلي.

موعد استخدام النمط

استعمل هذا النمط عند الحاجة لتخزين الكيانات التي يتجاوز حجمها أو عدد خصائصها حدود كيان فردي في خدمة الجدول.

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

نمط الكيانات الكبيرة

استعمل تخزين كائن ثنائي كبير الحجم لتخزين قيم الخصائص الكبيرة.

السياق والمشكلة

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

حل

في حالة تخطي حجم الكيان 1 ميغابايت لأن موقعًا واحدًا أو أكثر يحتوي على كمية كبيرة من البيانات، فإنه يمكنك تخزين البيانات في خدمة Blob ثم تخزين عنوان النقطة في خاصية في الكيان. على سبيل المثال، بمقدورك تخزين صورة موظف في وحدة تخزين كائن ثنائي كبير الحجم وتخزين رابط إلى الصورة في خاصية ⁧⁩صورة⁧⁩ الخاصة بكيان الموظف:

Graphic showing employee entity with string for Photo pointing to Blob storage

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

  • للحفاظ على التناسق النهائي بين الكيان في خدمة الجدول والبيانات الموجودة في خدمة Blob، استخدم ⁧⁩ نمط المعاملات المتسق في النهاية ⁧⁩ للحفاظ على الكيانات الخاصة بك.
  • يتضمن استرداد كيان كامل عمليتي تخزين على الأقل: واحدة لاسترداد الكيان والأخرى لاسترداد بيانات كائن ثنائي كبير الحجم.

موعد استخدام النمط

استخدم هذا النمط عندما تحتاج إلى تخزين الكيانات التي يتجاوز حجمها حدود كيان فردي في خدمة Table .

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

إعداد/إلحاق مكافحة النمط

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

السياق والمشكلة

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

Entity structure

حل

تتجنب بنية الكيان البديل التالية نقطة فعالة على أي قسم معين حيث يسجل التطبيق الأحداث:

Alternative entity structure

لاحظ من هذا المثال كيف أن كل من ⁧⁩ PartitionKey ⁧⁩ و⁧⁩ RowKey ⁧⁩ هما مفتاحان مركبان. يستخدم ⁧⁩ PartitionKey ⁧⁩ كلاً من معرف القسم والموظف لتوزيع التسجيل عبر أقسام متعددة.

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

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

موعد استخدام النمط

تجنب الإعداد/الإلحاق المكافح للنمط عندما يكون من المحتمل أن يؤدي حجم المعاملات إلى اختناق بواسطة خدمة التخزين عند الوصول إلى قسم ساخن.

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

سجل البيانات المكافحة للنمط

عادة، يجب عليك استخدام خدمة Blob بدلاً من خدمة Table لتخزين بيانات السجل.

السياق والمشكلة

من حالات الاستخدام الشائعة لبيانات السجل استرداد مجموعة مختارة من إدخالات السجل لنطاق تاريخ / وقت محدد: على سبيل المثال، تريد العثور على جميع رسائل الخطأ والحرجة التي قام التطبيق بتسجيلها بين 15:04 و15:06 على موعد محدد. لا تريد استخدام تاريخ ووقت رسالة السجل لتحديد القسم الذي تحفظ فيه كيانات السجل: ينتج عنه قسم فعال لأنه في أي وقت، ستشترك جميع كيانات السجل في نفس ⁧⁩PartitionKey⁧⁩ (راجع قسم ⁧⁩ إضافة / إلحاق النمط المكافح ⁧⁩). على سبيل المثال، ينتج عن مخطط الكيان التالي لرسالة السجل قسم فعال لأن التطبيق يكتب جميع رسائل السجل إلى القسم للتاريخ والساعة الحاليين:

Log message entity

في هذا المثال، يتضمن ⁧⁩RowKey⁧⁩ تاريخ ووقت رسالة السجل؛ لضمان تخزين رسائل السجل مرتبة بترتيب التاريخ/الوقت، ويتضمن معرف رسالة في حالة مشاركة رسائل سجل متعددة في نفس التاريخ والوقت.

توجد طريقة أخرى تتمثل في استخدام ⁧⁩PartitionKey⁧⁩ الذي يضمن أن التطبيق يكتب الرسائل عبر مجموعة من الأقسام. على سبيل المثال، إن كان مصدر رسالة السجل يوفر طريقة لتوزيع الرسائل عبر العديد من الأقسام، يمكنك استخدام مخطط الكيان التالي:

Alternative log message entity

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

حل

سلط القسم السابق الضوء على مشكلة محاولة استخدام خدمة Table لتخزين إدخالات السجل واقترح تصميمين غير مرضيين. أدى أحد الحلول إلى وجود قسم فعال مع خطر ضعف الأداء في كتابة رسائل السجل؛ أدى الحل الآخر إلى ضعف أداء الاستعلام بسبب الحاجة إلى فحص كل قسم في الجدول لاسترداد رسائل السجل لفترة زمنية محددة. يوفر تخزين كائن ثنائي كبير الحجم Blob حلاً أفضل لهذا النوع من السيناريو وهذه هي الطريقة التي يخزن بها Azure Storage Analytics بيانات السجل التي يجمعها.

يبين هذا القسم كيفية تخزين Storage Analytics لبيانات السجل في مساحة تخزين blob كتوضيح لهذا النهج لتخزين البيانات التي تستفسر عنها عادة حسب النطاق.

يخزن Storage Analytics رسائل السجل بتنسيق محدد في العديد من الكائنات الثنائية كبيرة الحجم. يسهل التنسيق المحدد على تطبيق العميل تحليل البيانات في رسالة السجلات.

يستخدم Storage Analytics اصطلاح تسمية للنقاط التي تمكنك من تحديد موقع الكائن ثنائي كبير الحجم (أو الكائنات الثنائية كبيرة الحجم) التي تحتوي على رسائل السجل التي تبحث عنها. على سبيل المثال، يحتوي الكائن ثنائي الحجم الكبير المسمى "queue / 2014/07/31/1800 / 000001.log" على رسائل السجل التي تتعلق بخدمة قائمة الانتظار للساعة التي تبدأ في الساعة 18:00 في 31 يوليو 2014. يشير "000001" إلى أن هذا هو ملف السجل الأول لهذه المدة الزمنية. ويسجل Storage Analytics أيضًا الطوابع الزمنية لرسائل السجل الأولى والأخيرة المخزنة في الملف كجزء من بيانات التعريف للكائن ثنائي كبير الحجم. وتمكنك واجهة برمجة التطبيقات لتخزين الكائنات الثنائية كبيرة الحجم من تحديد موقع النقط في حاوية استنادًا إلى بادئة اسم: لتحديد موقع جميع الكائنات الثنائية كبيرة الحجم التي تحتوي على بيانات سجل قائمة الانتظار للساعة التي تبدأ من الساعة 18:00، يمكنك استخدام البادئة "queue/2014/07/31/1800".

تقوم Storage Analytics بتخزين الرسائل مؤقتًا داخليًا ثم يقوم بتحديث النقطة المناسبة بشكل دوري أو إنشاء واحدة جديدة تحتوي على أحدث دفعة من إدخالات السجل. ويقلل هذا من عدد عمليات الكتابة التي يجب أن تقوم بها إلى خدمة Blo.

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

المسائل والاعتبارات

ضع في اعتبارك النقاط التالية عند تحديد طريقة تخزين بيانات السجل:

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

اعتبارات التنفيذ

يتناول هذا القسم بعض الاعتبارات التي يجب مراعاتها عند تنفيذ الأنماط الموضحة في الأقسام السابقة. يستخدم معظم هذا القسم أمثلة مكتوبة بلغة C # تستخدم مكتبة عميل التخزين (الإصدار 4.3.0 وقت كتابة هذا التقرير).

استرداد الكيانات

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

تنفيذ استعلام نقطي باستخدام Storage Client Library

أسهل طريقة لتنفيذ استعلام نقطي هي استخدام طريقة ⁧⁩ GetEntityAsync ⁧⁩ كما هو موضح في مقتطف رمز C # التالي الذي يسترد كيانًا به ⁧⁩ PartitionKey ⁧⁩ قيمة "مبيعات" و⁧⁩ مفتاح الصف ⁧⁩ للقيمة "212":

var retrieveResult = employeeTable.GetEntityAsync<EmployeeEntity>("Sales", "212");
if (retrieveResult.Result != null)
{
    EmployeeEntity employee = (EmployeeEntity)queryResult.Result;
    ...
}  

لاحظ كيف يتوقع هذا المثال أن يكون الكيان الذي يسترده من النوع ⁧⁩ EmployeeEntity ⁧⁩.

استرداد كيانات عديدة باستخدام LINQ

بمقدورك استخدام LINQ لاسترداد كيانات متعددة من خدمة الجدول عند العمل مع مكتبة Microsoft Azure Cosmos Table القياسية.

dotnet add package Microsoft.Azure.Cosmos.Table

لإنجاح الأمثلة التالية، ستحتاج إلى إدراج مساحات أسماء:

using System.Linq;
using Azure.Data.Table

إن EmployeeTable هو كائن CloudTable يقوم بتنفيذ طريقة CreateQuery ⁧<⁩ ITableEntity ⁧>⁩ ()، والتي تُرجع TableQuery ⁧<⁩ ITableEntity ⁧>⁩. تقوم العناصر من هذا النوع بتطبيق IQueryable وتسمح باستخدام كل من LINQ Query Expressions وdot notation syntax.

استرداد كيانات متعددة، ويتم تحقيق ذلك عن طريق تحديد استعلام باستخدام عبارة ⁧⁩ عامل التصفية ⁧⁩. لتجنب فحص الجداول، يجب عليك دائمًا تضمين قيمة ⁧⁩ PartitionKey ⁧⁩ في عبارة التصفية، وقيمة ⁧⁩ RowKey ⁧⁩ إن أمكن لتجنب عمليات فحص الجدول والأقسام. تدعم خدمة Table مجموعة محدودة من عوامل المقارنة (أكبر من أو أكبر من أو يساوي أو أقل من أو أقل من أو يساوي أو يساوي أو لا يساوي) لاستخدامها في عبارة التصفية.

يعثر مقتطف التعليمة البرمجية C # التالي على جميع الموظفين الذين تبدأ أسماؤهم بالحرف "B" (على افتراض أن ⁧⁩ RowKey ⁧⁩ يخزن الاسم الأخير) في قسم المبيعات (على افتراض أن ⁧⁩ PartitionKey ⁧⁩ يخزن القسم اسم):

var employees = employeeTable.Query<EmployeeEntity>(e => (e.PartitionKey == "Sales" && e.RowKey.CompareTo("B") >= 0 && e.RowKey.CompareTo("C") < 0));  

لاحظ كيف يحدد الاستعلام كلاً من ⁧⁩ RowKey ⁧⁩ و⁧⁩ PartitionKey ⁧⁩ لضمان أداء أفضل.

يُظهر نموذج التعليمات البرمجية التالي وظائف مكافئة بدون استخدام بناء جملة LINQ:

var employees = employeeTable.Query<EmployeeEntity>(filter: $"PartitionKey eq 'Sales' and RowKey ge 'B' and RowKey lt 'C'");  

ملاحظة

تتضمن طرق ⁧⁩الاستعلام⁧⁩ شروط عامل التصفية الثلاثة.

استرداد أعداد كبيرة من الكيانات باستخدام استعلام

يسترد الاستعلام الأمثل كيان فردي استنادًا إلى قيمة ⁧⁩PartitionKey⁧⁩ وقيمة ⁧⁩RowKey⁧⁩. ولكن في بعض السيناريوهات قد يكون لديك شرط لإرجاع العديد من الكيانات من نفس القسم أو حتى من العديد من الأقسام.

ينبغي لك دائما اختبار أداء التطبيق الخاص بك بشكل كامل في مثل هذه السيناريوهات.

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

إذا كنت تستخدم Table Client Library، فإنه يمكنها تلقائيًا معالجة الرموز المميزة للاستمرار نيابة عنك في أثناء إرجاع الكيانات من خدمة Table. يتعامل نموذج التعليمة البرمجية C # التالي باستخدام Table Client Library تلقائيًا مع الرموز المميزة للاستمرار إذا أعادتها خدمة Table في استجابة:

var employees = employeeTable.Query<EmployeeEntity>("PartitionKey eq 'Sales'")

foreach (var emp in employees)
{
    // ...
}  

تتعامل التعليمة البرمجية C # التالية مع الرموز المميزة للاستمرار بشكل صريح:

TableContinuationToken continuationToken = null;
do
{
    var employees = employeeTable.Query<EmployeeEntity>("PartitionKey eq 'Sales'");
    foreach (var emp in employees.AsPages())
    {
        // ...
        continuationToken = emp.ContinuationToken;
    }
    
} while (continuationToken != null);  

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

  • يمكّنك من تحديد كمية البيانات المراد استردادها من خدمة الجدول والتي يمكنك نقلها عبر الشبكة.
  • بمقدورك إجراء IO غير متزامن في .NET.
  • يمكّنك من إجراء تسلسل لرمز الاستمرارية للتخزين الدائم حتى تتمكن من المتابعة في حالة تعطل التطبيق.

ملاحظة

عادة ما يقوم الرمز المميز للاستمرار بإرجاع مقطع يحتوي على 1000 كيان، على الرغم من أنه قد يكون أقل. هذا هو الحال أيضًا إذا قمت بتحديد عدد الإدخالات التي يعرضها الاستعلام باستخدام ⁧⁩ Take ⁧⁩ لإرجاع الكيانات n الأولى التي تطابق معايير البحث الخاصة بك: قد تعرض خدمة الجدول مقطعًا يحتوي على أقل من n كيانات مع رمز استمرار لتمكينك من استرداد الكيانات المتبقية.

تبين التعليمة البرمجية C # التالية طريقة تعديل عدد الكيانات التي تم إرجاعها داخل شريحة:

employees.max = 50;  

إسقاط من جانب الخادم

يمكن أن يحتوي كيان واحد على ما يصل إلى 255 خاصية ويصل حجمها إلى 1 ميغابايت. عند الاستعلام عن الجدول واسترداد الكيانات، قد لا تحتاج إلى كل الخصائص ويمكنك تجنب نقل البيانات دون داع (للمساعدة في تقليل زمن الانتقال والتكلفة). بمقدورك استخدام الإسقاط من جانب الخادم لنقل الخصائص التي تحتاجها فقط. يسترد المثال التالي خاصية ⁧⁩ البريد الإلكتروني ⁧⁩ فقط (جنبًا إلى جنب مع ⁧⁩ PartitionKey ⁧⁩ و⁧⁩ RowKey ⁧⁩ و⁧⁩ الطابع الزمني ⁧⁩ و⁧⁩ ETag ⁧⁩) من الكيانات المحددة بواسطة الاستعلام.

var subsetResults  = query{
    for employee in employeeTable.Query<EmployeeEntity>("PartitionKey eq 'Sales'") do
    select employee.Email
}
foreach (var e in subsetResults)
{
    Console.WriteLine("RowKey: {0}, EmployeeEmail: {1}", e.RowKey, e.Email);
}  

لاحظ كيف تتوفر قيمة ⁧⁩ RowKey ⁧⁩ على الرغم من عدم تضمينها في قائمة الخصائص المراد استردادها.

تعديل طارئة على الكيانات

تتيح لك مكتبة عميل التخزين Storage Client Library تعديل الكيانات المخزنة في خدمة الجدول عن طريق إدراج الكيانات وحذفها وتحديثها. يمكنك استعمال EGTs لتجميع عمليات الإدراج المتعددة وتحديثها وحذفها معًا لتقليل عدد الرحلات ذهابًا وإيابًا المطلوبة وتحسين أداء الحل الخاص بك.

عادةً ما تتضمن الاستثناءات التي يتم طرحها عند تنفيذ "مكتبة عميل التخزين" EGT فهرس الكيان الذي تسبب في فشل الدُفعة. هذا مفيد عندما تقوم بتصحيح التعليمات البرمجية التي تستخدم EGTs.

ينبغي لك أيضًا التفكير في طريقة تأثير التصميم الخاص بك على كيفية تعامل تطبيق العميل مع عمليات التزامن والتحديث.

إدارة عملية التزامن

بشكل افتراضي، تنفذ خدمة الجدول عمليات تحقق أفضل للتزامن على مستوى الكيانات الفردية لعمليات ⁧⁩ إدراج ⁧⁩ و⁧⁩ دمج ⁧⁩ و⁧⁩ حذف ⁧⁩، على الرغم من إمكانية ذلك للعميل لفرض خدمة الجدول لتجاوز هذه الفحوصات. لمزيد من المعلومات حول كيفية إدارة خدمة الجدول للتزامن، راجع ⁧⁩ إدارة التزامن في Microsoft Azure Storage ⁧⁩.

ميزة الدمج أو الاستبدال

تحل طريقة ⁧⁩ الاستبدال ⁧⁩ للفئة ⁧⁩ TableOperation ⁧⁩ دائمًا محل الكيان الكامل في خدمة الجدول. إذا لم تقم بتضمين خاصية في الطلب عندما تكون هذه الخاصية موجودة في الكيان المخزن، فإن الطلب يزيل تلك الخاصية من الكيان المخزن. ما لم ترغب في إزالة خاصية صراحةً من كيان مخزن، يجب عليك تضمين كل خاصية في الطلب.

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

ملاحظة

تفشل أساليب ⁧⁩ استبدال ⁧⁩ و⁧⁩ دمج ⁧⁩ في حالة عدم وجود الكيان. كبديل، يمكنك استخدام الأسلوبين ⁧⁩ InsertOrReplace ⁧⁩ و⁧⁩ InsertOrMerge ⁧⁩ اللذين ينشئان كيانًا جديدًا إذا لم يكن موجودًا.

التعامل مع أنواع الكيانات غير المتجانسة

خدمة Table عبارة عن مخزن جدول ⁧⁩ بدون مخطط ⁧⁩ ما يعني أن الجدول الواحد يمكنه تخزين كيانات من أنواع متعددة مما يوفر مرونة كبيرة في تصميمك. يوضح المثال التالي جدولاً يخزن كلاً من كيانات الموظف والقسم:

PartitionKey RowKey Timestamp
الاسم الأول اسم العائلة العمر بريد إلكتروني
الاسم الأول اسم العائلة العمر بريد إلكتروني
اسم القسم EmployeeCount
الاسم الأول اسم العائلة العمر بريد إلكتروني

يجب أن يظل كل كيان يحتوي على قيم ⁧⁩ PartitionKey ⁧⁩، و⁧⁩ RowKey ⁧⁩، و⁧⁩ الطابع الزمني ⁧⁩، ولكن قد يحتوي على أي مجموعة من الخصائص. علاوة على ذلك، لا يوجد ما يشير إلى نوع الكيان ما لم تختر تخزين هذه المعلومات في مكان ما. يوجد خياران لتحديد نوع الكيان:

  • ضع في البداية نوع الكيان إلى ⁧⁩ RowKey ⁧⁩ (أو ربما ⁧⁩ PartitionKey ⁧⁩). على سبيل المثال، ⁧⁩ EMPLOYEE_000123 ⁧⁩ أو ⁧⁩ DEPARTMENT_SALES ⁧⁩ كقيم ⁧⁩ RowKey ⁧⁩.
  • استعمل خاصية منفصلة لتسجيل نوع الكيان كما هو موضح في الجدول أدناه.
PartitionKey RowKey Timestamp
EntityType الاسم الأول اسم العائلة العمر بريد إلكتروني
الموظف
EntityType الاسم الأول اسم العائلة العمر بريد إلكتروني
الموظف
EntityType اسم القسم EmployeeCount
القسم
EntityType الاسم الأول اسم العائلة العمر بريد إلكتروني
الموظف

يكون الخيار الأول، قبل إضافة نوع الكيان إلى ⁧⁩ RowKey ⁧⁩، مفيدًا إذا كان هناك احتمال أن يكون لكيانين من نوعين مختلفين نفس قيمة المفتاح. يقوم أيضًا بتجميع الكيانات من نفس النوع معًا في القسم.

الأساليب التي تمت مناقشتها في هذا القسم وثيقة الصلة بشكل خاص بمناقشة ⁧⁩ علاقات الوراثة ⁧⁩ المذكورة سابقًا في هذا الدليل في مقالة ⁧⁩ علاقات النمذجة ⁧⁩.

ملاحظة

ينبغي لك التفكير في تضمين رقم إصدار في قيمة نوع الكيان لتمكين تطبيقات العميل من تطوير كائنات POCO والعمل مع إصدارات مختلفة.

يصف الجزء المتبقي من هذا القسم بعض الميزات الموجودة في مكتبة عميل التخزين التي تسهل العمل مع أنواع كيانات متعددة في نفس الجدول.

استردت أنواع الكيانات غير المتجانسة

إذا كنت تستخدم Table Client Library، فلديك ثلاثة خيارات للعمل مع أنواع كيانات متعددة.

إن كنت تعرف نوع الكيان المخزن بقيم ⁧⁩RowKey⁧⁩ و⁧⁩PartitionKey⁧⁩ محددة، فإنه يمكنك تحديد نوع الكيان عند استرداد الكيان كما هو موضح في المثالين السابقين اللذين يستبعدان كيانات من النوع ⁧⁩EmployeeEntity⁧⁩: ⁧⁩تنفيذ استعلام نقطة باستخدام مكتبة عميل التخزين⁧⁩⁧⁩واسترداد كيانات متعددة باستخدام LINQ.⁧

الخيار الثاني يتمثل في استخدام نوع ⁧⁩TableEntity⁧⁩ (حقيبة خصائص) بدلاً من نوع كيان POCO ملموس (قد يؤدي هذا الخيار أيضًا إلى تحسين الأداء لأنه ليست هناك حاجة إلى تسلسل الكيان وإلغاء تسلسله إلى أنواع .NET). من المحتمل قيام التعليمة البرمجية C# التالية باسترداد كيانات متعددة من أنواع مختلفة من الجدول، ولكنها ترجع كافة الكيانات كمثيلات ⁧⁩TableEntity⁧⁩ . ثم يستعمل الخاصية ⁧⁩EntityType⁧⁩ لتحديد نوع كل كيان:

Pageable<TableEntity> entities = employeeTable.Query<TableEntity>(x =>
    x.PartitionKey ==  "Sales" && x.RowKey.CompareTo("B") >= 0 && x.RowKey.CompareTo("F") <= 0)

foreach (var entity in entities)
{
    if (entity.GetString("EntityType") == "Employee")
    {
        // use entityTypeProperty, RowKey, PartitionKey, Etag, and Timestamp
    }
}  

لاسترداد خصائص أخرى ينبغي لك استخدام الأسلوب ⁧⁩GetString⁧⁩ على ⁧⁩كيان⁧⁩ فئة ⁧⁩TableEntity⁧⁩ .

تعديل أنواع الكيانات غير المتجانسة

لا تحتاج إلى معرفة نوع الكيان لحذفه، وتعرف دائمًا نوع الكيان عند إدراجه. ولكن يمكنك استخدام نوع ⁧⁩TableEntity⁧⁩ لتحديث كيان دون معرفة نوعه ودون استخدام فئة كيان POCO. يسترد نموذج التعليمات البرمجية التالي كيانًا واحدًا، ويتحقق من وجود الخاصية ⁧⁩EmployeeCount⁧⁩ قبل تحديثها.

var result = employeeTable.GetEntity<TableEntity>(partitionKey, rowKey);
TableEntity department = result.Value;
if (department.GetInt32("EmployeeCount") == null)
{
    throw new InvalidOperationException("Invalid entity, EmployeeCount property not found.");
}
 employeeTable.UpdateEntity(department, ETag.All, TableUpdateMode.Merge);

ضبط الوصول باستخدام تواقيع الوصول المشترك

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

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

لمزيد من المعلومات بشأن استخدام الرموز المميزة لـ SAS مع خدمة ⁧⁩الجدول، راجع استخدام توقيعات الوصول المشترك (SAS).⁧

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

من الممكن إنشاء رمز توقيعات الوصول المشترك (SAS)SAS مميز يمنح حق الوصول إلى مجموعة فرعية من الكيانات في جدول. بشكل افتراضي، يمكنك إنشاء رمز توقيعات الوصول المشترك (SAS) مميز لجدول بأكمله، ولكن من الممكن أيضًا تحديد أن الرمز المميز SAS يمنح حق الوصول إلى نطاق من قيم PartitionKey أو نطاق من قيم ⁧⁩PartitionKey⁧⁩ و⁧⁩RowKey⁧⁩.⁧⁩⁧⁩ يمكنك اختيار إنشاء رموز توقيعات الوصول المشترك (SAS) للمستخدمين الفرديين لنظامك بحيث يسمح رمز توقيعات الوصول المشترك (SAS) المميز لكل مستخدم فقط بالوصول إلى الكيانات الخاصة بهم في خدمة الجدول.

العمليات غير المتزامنة والمتوازية

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

ضمن مثيل العميل، يمكنك تحسين معدل النقل عن طريق تنفيذ عمليات التخزين بشكل غير متزامن. تسهل Storage Client Library كتابة الاستعلامات والتعديلات غير المتزامنة. على سبيل المثال، قد تبدأ بالطريقة المتزامنة التي تسترد كافة الكيانات الموجودة في قسم على النحو الموضح في التعليمات البرمجية C # التالية:

private static void ManyEntitiesQuery(TableClient employeeTable, string department)
{
    TableContinuationToken continuationToken = null;
    do
    {
        var employees = employeeTable.Query<EmployeeEntity>($"PartitionKey eq {department}");
        foreach (var emp in employees.AsPages())
        {
            // ...
            continuationToken = emp.ContinuationToken;
        }
        
    } while (continuationToken != null);
}  

يمكنك بسهولة تعديل هذه التعليمة البرمجية بحيث يتم تشغيل الاستعلام بشكل غير متزامن على نحو ما يلي:

private static async Task ManyEntitiesQueryAsync(TableClient employeeTable, string department)
{
    TableContinuationToken continuationToken = null;
    do
    {
        var employees = await employeeTable.QueryAsync<EmployeeEntity>($"PartitionKey eq {department}");
        foreach (var emp in employees.AsPages())
        {
            // ...
            continuationToken = emp.ContinuationToken;
        }

    } while (continuationToken != null);
}  

في هذا المثال غير المتزامن، بمقدورك رؤية التغييرات التالية من الإصدار المتزامن:

  • يتضمن توقيع الأسلوب الآن المعدل ⁧⁩غير المتزامن⁧⁩ وإرجاع مثيل ⁧⁩مهمة⁧⁩ .
  • عوضًا عن استدعاء أسلوب ⁧⁩الاستعلام⁧⁩ لاسترداد النتائج، تستدعي الطريقة الآن أسلوب ⁧⁩QueryAsync⁧⁩ وتستخدم معدل ⁧⁩الانتظار⁧⁩ لاسترداد النتائج بشكل غير متزامن.

يمكن لتطبيق العميل استدعاء هذا الأسلوب عدة مرات (بقيم مختلفة لمعلمة ⁧⁩القسم⁧⁩ )، وسيتم تشغيل كل استعلام على مؤشر ترابط منفصل.

بمقدورك أيضًا إدراج الكيانات وتحديثها وحذفها بشكل غير متزامن. يبين مثال C # التالي طريقة بسيطة ومتزامنة لإدراج كيان موظف أو استبداله:

private static void SimpleEmployeeUpsert(
    TableClient employeeTable,
    EmployeeEntity employee)
{
    var result = employeeTable.UpdateEntity(employee, Azure.ETag.All, TableUpdateMode.Replace);
    Console.WriteLine("HTTP Status: {0}", result.Status);
}  

يمكنك بسهولة ويسر تعديل هذه التعليمة البرمجية بحيث يتم تشغيل التحديث بشكل غير متزامن كما يلي:

private static async Task SimpleEmployeeUpsertAsync(
    TableClient employeeTable,
    EmployeeEntity employee)
{
    var result = await employeeTable.UpdateEntityAsync(employee, Azure.ETag.All, TableUpdateMode.Replace);
    Console.WriteLine("HTTP Status: {0}", result.Result.Status);
}  

في هذا المثال غير المتزامن، بمقدورك رؤية التغييرات التالية من الإصدار المتزامن:

  • يتضمن توقيع الأسلوب الآن المعدل ⁧⁩غير المتزامن⁧⁩ وإرجاع مثيل ⁧⁩مهمة⁧⁩ .
  • عوضًا عن استدعاء الأسلوب ⁧⁩تنفيذ⁧⁩ لتحديث الكيان، تستدعي الطريقة الآن الأسلوب ⁧⁩ExecuteAsync⁧⁩ وتستخدم معدل ⁧⁩الانتظار⁧⁩ لاسترداد النتائج بشكل غير متزامن.

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

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