البرنامج التعليمي: تحسين الفهرسة مع واجهة برمجة التطبيقات الدفع

يدعم Azure الذكاء الاصطناعي Search نهجين أساسيين لاستيراد البيانات إلى فهرس بحث: دفع بياناتك إلى الفهرس برمجيا، أو توجيه مفهرس Azure الذكاء الاصطناعي Search إلى مصدر بيانات مدعوم لسحب البيانات.

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

يستخدم هذا البرنامج التعليمي C# ومكتبة Azure.Search.Documents من Azure SDK ل .NET لتنفيذ المهام التالية:

  • إنشاء فهرس
  • اختبار أحجام دفعة مختلفة لتحديد حجم الأكثر كفاءة
  • دفعات الفهرس بشكل غير متزامن
  • استخدام مؤشرات ترابط متعددة لزيادة سرعات الفهرسة
  • استخدام استراتيجية إعادة محاولة التراجع الأسي لإعادة محاولة المستندات الفاشلة

في حال لم يكن لديك اشتراك Azure، فأنشئ حساباً مجانيّاً قبل البدء.

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

الخدمات والأدوات التالية مطلوبة لهذا البرنامج التعليمي.

تحميل الملفات

توجد التعليمات البرمجية المصدر لهذا البرنامج التعليمي في المجلد optimize-data-indexing/v11 في مستودع GitHub Azure-Samples/azure-search-dotnet-samples .

الاعتبارات

يتم بعد ذلك سرد العوامل التي تؤثر على سرعات الفهرسة. يمكنك معرفة المزيد في فهرسة مجموعات البيانات الكبيرة.

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

1 - إنشاء Azure الذكاء الاصطناعي خدمة البحث

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

يستخدم هذا البرنامج التعليمي المصادقة المستندة إلى المفتاح. انسخ مفتاح API للمسؤول للصقه في ملف appsettings.json .

  1. سجل الدخول إلى مدخل Microsoft Azure، وفي صفحة نظرة عامة على خدمة البحث، احصل على عنوان URL. قد يبدو مثال نقطة النهاية بالشكل https://mydemo.search.windows.net.

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

    Get an HTTP endpoint and access key

2 - إعداد بيئتك

  1. بدء Visual Studio وفتح OptimizeDataIndexing.sln.
  2. في مستكشف الحلول، افتح appsettings.js لتوفير معلومات الاتصال.
{
  "SearchServiceUri": "https://{service-name}.search.windows.net",
  "SearchServiceAdminApiKey": "",
  "SearchIndexName": "optimize-indexing"
}

3 - استكشاف التعليمات البرمجية

بمجرد تحديث appsettings.jsعلى، يجب أن يكون البرنامج النموذجي في OptimizeDataIndexing.sln جاهزا للبناء وتشغيله.

هذه التعليمة البرمجية مشتقة من قسم C# من Quickstart: البحث عن النص الكامل باستخدام Azure SDKs. يمكنك العثور على معلومات أكثر تفصيلا حول أساسيات العمل مع SDK.NET في تلك المقالة.

هذا التطبيق وحدة التحكم C#/.NET بسيط ينفذ المهام التالية:

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

قبل تشغيل البرنامج، خذ دقيقة لدراسة الكود وتعريفات الفهرس لهذه العينة. الأكواد ذات الصلة في عدة ملفات:

  • يحتوي .cs الفندق والعنوان.cs على المخطط الذي يعرف الفهرس
  • DataGenerator.cs يحتوي على فئة بسيطة لتسهيل إنشاء كميات كبيرة من بيانات الفندق
  • يحتوي ExponentialBackoff.cs على تعليمات برمجية لتحسين عملية الفهرسة كما هو موضح في هذه المقالة
  • يحتوي Program.cs على دالات تنشئ وحذف فهرس Azure الذكاء الاصطناعي Search، وفهرسة دفعات من البيانات، وتختبر أحجام دفعات مختلفة

إنشاء الفهرس

يستخدم هذا البرنامج النموذجي Azure SDK ل .NET لتعريف وإنشاء فهرس Azure الذكاء الاصطناعي Search. يستفيد من الفئة FieldBuilder لإنشاء بنية فهرس من فئة نموذج بيانات C#‎.

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

توضح المقتطفات التالية من ملف Hotel.cs كيفية تحديد حقل واحد ومرجع إلى فئة طراز بيانات أخرى.

. . .
[SearchableField(IsSortable = true)]
public string HotelName { get; set; }
. . .
public Address Address { get; set; }
. . .

في ملف البرنامج.cs، يتم تعريف الفهرس باسم ومجموعة حقول تم إنشاؤها بواسطة FieldBuilder.Build(typeof(Hotel)) الأسلوب، ثم تم إنشاؤه كما يلي:

private static async Task CreateIndexAsync(string indexName, SearchIndexClient indexClient)
{
    // Create a new search index structure that matches the properties of the Hotel class.
    // The Address class is referenced from the Hotel class. The FieldBuilder
    // will enumerate these to create a complex data structure for the index.
    FieldBuilder builder = new FieldBuilder();
    var definition = new SearchIndex(indexName, builder.Build(typeof(Hotel)));

    await indexClient.CreateIndexAsync(definition);
}

إنشاء بيانات

يتم تطبيق فئة بسيطة في ملف DataGenerator.cs لإنشاء بيانات للاختبار. الغرض الوحيد من هذه الفئة هو تسهيل إنشاء عدد كبير من المستندات ذات المعرف الفريد للفهرسة.

للحصول على قائمة تضم 100,000 فندق بمعرفات فريدة، قم بتشغيل الأسطر التالية من التعليمات البرمجية:

long numDocuments = 100000;
DataGenerator dg = new DataGenerator();
List<Hotel> hotels = dg.GetHotels(numDocuments, "large");

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

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

4 - اختبار أحجام الدفعات

يدعم Azure الذكاء الاصطناعي Search واجهات برمجة التطبيقات التالية لتحميل مستندات مفردة أو متعددة في فهرس:

فهرسة المستندات على دفعات سوف تحسن بشكل كبير أداء الفهرسة. يمكن أن تصل هذه الدفعات إلى 1000 مستند، أو ما يصل إلى حوالي 16 ميغابايت لكل دفعة.

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

  • مخطط الفهرس الخاص بك
  • حجم بياناتك

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

توضح الدالة التالية أسلوب بسيط لاختبار أحجام الدفعات.

public static async Task TestBatchSizesAsync(SearchClient searchClient, int min = 100, int max = 1000, int step = 100, int numTries = 3)
{
    DataGenerator dg = new DataGenerator();

    Console.WriteLine("Batch Size \t Size in MB \t MB / Doc \t Time (ms) \t MB / Second");
    for (int numDocs = min; numDocs <= max; numDocs += step)
    {
        List<TimeSpan> durations = new List<TimeSpan>();
        double sizeInMb = 0.0;
        for (int x = 0; x < numTries; x++)
        {
            List<Hotel> hotels = dg.GetHotels(numDocs, "large");

            DateTime startTime = DateTime.Now;
            await UploadDocumentsAsync(searchClient, hotels).ConfigureAwait(false);
            DateTime endTime = DateTime.Now;
            durations.Add(endTime - startTime);

            sizeInMb = EstimateObjectSize(hotels);
        }

        var avgDuration = durations.Average(timeSpan => timeSpan.TotalMilliseconds);
        var avgDurationInSeconds = avgDuration / 1000;
        var mbPerSecond = sizeInMb / avgDurationInSeconds;

        Console.WriteLine("{0} \t\t {1} \t\t {2} \t\t {3} \t {4}", numDocs, Math.Round(sizeInMb, 3), Math.Round(sizeInMb / numDocs, 3), Math.Round(avgDuration, 3), Math.Round(mbPerSecond, 3));

        // Pausing 2 seconds to let the search service catch its breath
        Thread.Sleep(2000);
    }

    Console.WriteLine();
}

نظرا لأن المستندات ليست كلها بنفس الحجم (على الرغم من أنها موجودة في هذه العينة)، فإننا نقدر حجم البيانات التي نرسلها إلى خدمة البحث. نقوم بذلك باستخدام الدالة أدناه التي تقوم أولا بتحويل الكائن إلى json ثم تحدد حجمه بـ البايت. تسمح لنا هذه التقنية بتحديد أحجام الدفعات الأكثر كفاءة من حيث سرعات الفهرسة MB/s.

// Returns size of object in MB
public static double EstimateObjectSize(object data)
{
    // converting object to byte[] to determine the size of the data
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    byte[] Array;

    // converting data to json for more accurate sizing
    var json = JsonSerializer.Serialize(data);
    bf.Serialize(ms, json);
    Array = ms.ToArray();

    // converting from bytes to megabytes
    double sizeInMb = (double)Array.Length / 1000000;

    return sizeInMb;
}

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

await TestBatchSizesAsync(searchClient, numTries: 3);

عند تشغيل الدالة، يجب أن تشاهد إخراج مثل أدناه في وحدة التحكم الخاصة بك:

Output of test batch size function

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

5 - بيانات الفهرس

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

  • يستخدم مؤشرات ترابط/عمال متعددين.
  • تنفيذ استراتيجية إعادة محاولة التراجع الأسي.

إلغاء التعليق من 41 إلى 49 وإعادة تشغيل البرنامج. في هذا التشغيل، يقوم النموذج بإنشاء وإرسال دفعات من المستندات، حتى 100000 إذا قمت بتشغيل التعليمات البرمجية دون تغيير المعلمات.

استخدام مؤشرات ترابط/عمال متعددين

للاستفادة الكاملة من سرعات فهرسة Azure الذكاء الاصطناعي Search، استخدم مؤشرات ترابط متعددة لإرسال طلبات الفهرسة الدفعية بشكل متزامن إلى الخدمة.

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

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

  • 503 الخدمة غير متوفرة - يعني هذا الخطأ أن النظام تحت تحميل كثيف ولا يمكن معالجة طلبك في هذا الوقت.
  • 207 متعددة الحالة - يعني هذا الخطأ نجاح بعض المستندات، ولكن فشل واحد على الأقل.

تنفيذ استراتيجية إعادة محاولة التراجع الأسي

في حالة حدوث فشل، يجب إعادة محاولة الطلبات باستخدام استراتيجية إعادة محاولة التراجع الأسي.

يقوم Azure الذكاء الاصطناعي Search.NET SDK تلقائيا بإعادة محاولة 503s والطلبات الفاشلة الأخرى ولكن يجب عليك تنفيذ المنطق الخاص بك لإعادة محاولة 207s. يمكن أن تكون الأدوات مفتوحة المصدر مثل Polly مفيدة في استراتيجية إعادة المحاولة.

في هذه العينة، ونحن تنفيذ استراتيجية إعادة المحاولة الخلفية الأسية الخاصة بنا. نبدأ بتعريف بعض المتغيرات بما في maxRetryAttempts ذلك و الأولي delay لطلب فاشل:

// Create batch of documents for indexing
var batch = IndexDocumentsBatch.Upload(hotels);

// Create an object to hold the result
IndexDocumentsResult result = null;

// Define parameters for exponential backoff
int attempts = 0;
TimeSpan delay = delay = TimeSpan.FromSeconds(2);
int maxRetryAttempts = 5;

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

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

// Implement exponential backoff
do
{
    try
    {
        attempts++;
        result = await searchClient.IndexDocumentsAsync(batch).ConfigureAwait(false);

        var failedDocuments = result.Results.Where(r => r.Succeeded != true).ToList();

        // handle partial failure
        if (failedDocuments.Count > 0)
        {
            if (attempts == maxRetryAttempts)
            {
                Console.WriteLine("[MAX RETRIES HIT] - Giving up on the batch starting at {0}", id);
                break;
            }
            else
            {
                Console.WriteLine("[Batch starting at doc {0} had partial failure]", id);
                Console.WriteLine("[Retrying {0} failed documents] \n", failedDocuments.Count);

                // creating a batch of failed documents to retry
                var failedDocumentKeys = failedDocuments.Select(doc => doc.Key).ToList();
                hotels = hotels.Where(h => failedDocumentKeys.Contains(h.HotelId)).ToList();
                batch = IndexDocumentsBatch.Upload(hotels);

                Task.Delay(delay).Wait();
                delay = delay * 2;
                continue;
            }
        }

        return result;
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine("[Batch starting at doc {0} failed]", id);
        Console.WriteLine("[Retrying entire batch] \n");

        if (attempts == maxRetryAttempts)
        {
            Console.WriteLine("[MAX RETRIES HIT] - Giving up on the batch starting at {0}", id);
            break;
        }

        Task.Delay(delay).Wait();
        delay = delay * 2;
    }
} while (true);

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

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

await ExponentialBackoff.IndexData(indexClient, hotels, 1000, 8);

عند تشغيل الدالة، يجب أن تشاهد الإخراج كما يلي:

Output of index data function

عند فشل دفعة من المستندات، تتم طباعة خطأ يشير إلى الفشل وإعادة محاولة الدفعة:

[Batch starting at doc 6000 had partial failure]
[Retrying 560 failed documents]

بعد انتهاء تشغيل الدالة، يمكنك التحقق من أن جميع المستندات تمت إضافتها إلى الفهرس.

6 - استكشاف الفهرس

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

برمجيا

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

عد المستندات

عملية Count Documents استرداد عدد المستندات في فهرس بحث:

long indexDocCount = await searchClient.GetDocumentCountAsync();

الحصول على إحصائيات الفهرس

ترجع عملية Get Index Statistics عدد مستندات للفهرس الحالي، بالإضافة إلى استخدام التخزين. سوف يستغرق تحديث إحصائيات الفهرس وقتا أطول من عدد المستندات.

var indexStats = await indexClient.GetIndexStatisticsAsync(indexName);

مدخل Azure

في مدخل Microsoft Azure، من جزء التنقل الأيمن، ابحث عن فهرس تحسين الفهرسة في قائمة الفهارس .

List of Azure AI Search indexes

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

إعادة تعيين وإعادة تشغيل

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

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

يمكنك أيضاً استخدام المدخل لحذف الفهارس.

تنظيف الموارد

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

يمكن العثور على الموارد وإدارتها في المدخل الإلكتروني، باستخدامAll resources أو رابط Resource groups الموجود في جزء التنقل الأيسر.

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

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