Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Azure AI Search podporuje dva základní přístupy k importu dat do indexu vyhledávání: odeslání dat do indexu programově nebo načtení dat nasměrováním indexeru Azure AI Search na podporovaný zdroj dat.
V tomto kurzu se dozvíte, jak efektivně indexovat data pomocí push modelu dávkováním požadavků a použitím exponenciální strategie opakování. Ukázkovou aplikaci si můžete stáhnout a spustit. Tento kurz také vysvětluje klíčové aspekty aplikace a faktory, které je potřeba vzít v úvahu při indexování dat.
V tomto kurzu použijete jazyk C# a knihovnu Azure.Search.Documents ze sady Azure SDK pro .NET k:
- Vytvoření indexu
- Otestujte různé velikosti dávek, abyste zjistili nejúčinnější velikost.
- Asynchronní indexové dávky
- Použití více vláken ke zvýšení rychlosti indexování
- Použijte exponenciální strategii pro opětovné pokusy u neúspěšných dokumentů.
Požadavky
- Účet Azure s aktivním předplatným. Vytvoření účtu zdarma
- Visual Studio.
Stažení souborů
Zdrojový kód pro tento kurz je ve složce optimize-data-indexing/v11 v úložišti GitHub Azure-Samples/azure-search-dotnet-scale .
Klíčové aspekty
Následující faktory ovlivňují rychlosti indexování. Další informace najdete v tématu Indexování velkých datových sad.
- Úroveň služby a počet oddílů/replik: Přidání oddílů nebo upgrade úrovně zvyšuje rychlost indexování.
- Složitost schématu indexu: Přidávání polí a vlastností polí snižuje rychlost indexování. Menší indexy jsou rychlejší k indexování.
- Velikost dávky: Optimální velikost dávky se liší podle schématu indexu a datové sady.
- Počet vláken/pracovních procesů: Jedno vlákno nevyužívá plnou výhodu rychlosti indexování.
- Strategie opakování: Strategie exponenciálního opakování je osvědčeným postupem pro optimální indexování.
- Rychlost přenosu dat v síti: Rychlost přenosu dat může být omezujícím faktorem. Indexujte data z prostředí Azure, abyste zvýšili rychlost přenosu dat.
Vytvořit službu vyhledávání Azure AI
Tento kurz vyžaduje službu Azure AI Search, kterou můžete vytvořit na webu Azure Portal. Můžete také najít existující službu ve vašem aktuálním předplatném. K přesnému testování a optimalizaci rychlosti indexování doporučujeme použít stejnou úroveň, kterou plánujete použít v produkčním prostředí.
Získání klíče správce a adresy URL služby Azure AI Search
V tomto kurzu se používá ověřování založené na klíčích. Zkopírujte klíč rozhraní API správce a vložte ho do souboru appsettings.json .
Přihlaste se k portálu Azure. Na stránce Přehled služby zkopírujte adresu URL koncového bodu. Příkladem koncového bodu může být
https://mydemo.search.windows.net
.V Nastavení>Klíče získejte klíč správce pro úplná práva ke službě. Existují dva zaměnitelné klíče správce, které jsou k dispozici pro zajištění kontinuity podnikových procesů v případě, že potřebujete jeden převést. Primární nebo sekundární klíč můžete použít u požadavků pro přidávání, úpravy a odstraňování objektů.
Nastavení prostředí
Spusťte Visual Studio a otevřete OptimizeDataIndexing.sln.
V Průzkumník řešení otevřete appsettings.json a zadejte informace o připojení vaší služby.
{
"SearchServiceUri": "https://{service-name}.search.windows.net",
"SearchServiceAdminApiKey": "",
"SearchIndexName": "optimize-indexing"
}
Prozkoumání kódu
Po aktualizaci appsettings.jsonby měl být ukázkový program v OptimizeDataIndexing.sln připravený k sestavení a spuštění.
Tento kód je odvozený z části Quickstart pro jazyk C# s názvem Fulltext Search using the Azure SDKs, která poskytuje podrobné informace o základech práce s .NET SDK.
Tato jednoduchá konzolová aplikace C#/.NET provádí následující úlohy:
- Vytvoří nový index založený na datové struktuře třídy C#
Hotel
(která také odkazuje naAddress
třídu). - Testuje různé velikosti dávek, aby bylo možné určit nejúčinnější velikost.
- Indexuje data asynchronně.
- Zvýšení rychlosti indexování pomocí více vláken
- Použití exponenciální strategie opakování k opětovnému zpracování neúspěšných položek
Než program spustíte, prostudujte si kód a definice indexu pro tuto ukázku. Příslušný kód je v několika souborech:
- Hotel.cs a Address.cs obsahují schéma definující index.
- DataGenerator.cs obsahuje jednoduchou třídu, která usnadňuje vytváření velkých objemů hotelových dat.
- ExponentialBackoff.cs obsahuje kód pro optimalizaci procesu indexování, jak je popsáno v tomto článku.
- Program.cs obsahuje funkce, které vytvářejí a odstraňuje index služby Azure AI Search, indexuje dávky dat a testuje různé velikosti dávek.
Vytvoření indexu
Tento ukázkový program používá sadu Azure SDK pro .NET k definování a vytvoření indexu Azure AI Search. Využívá třídu FieldBuilder
k vygenerování struktury indexu z třídy datového modelu jazyka C#.
Datový model je definován Hotel
třídou, která obsahuje také odkazy na Address
třídu.
FieldBuilder
přejde k podrobnostem více definic tříd, aby se pro index vygenerovala složitá datová struktura. Značky metadat slouží k definování atributů jednotlivých polí, jako je například to, jestli je prohledávatelné nebo řaditelné.
Následující fragmenty kódu ze souboru Hotel.cs určují jedno pole a odkaz na jinou třídu datového modelu.
. . .
[SearchableField(IsSortable = true)]
public string HotelName { get; set; }
. . .
public Address Address { get; set; }
. . .
V souboru Program.cs je index definován s názvem a kolekcí polí vygenerovanou FieldBuilder.Build(typeof(Hotel))
metodou a pak vytvořen následujícím způsobem:
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);
}
Vytvořit data
Jednoduchá třída je implementována v souboru DataGenerator.cs pro generování dat pro testování. Účelem této třídy je usnadnit generování velkého počtu dokumentů s jedinečným ID pro indexování.
Pokud chcete získat seznam 100 000 hotelů s jedinečnými ID, spusťte následující kód:
long numDocuments = 100000;
DataGenerator dg = new DataGenerator();
List<Hotel> hotels = dg.GetHotels(numDocuments, "large");
Pro testování v této ukázce jsou k dispozici dvě velikosti hotelů: malé a velké.
Schéma indexu ovlivňuje rychlost indexování. Po dokončení tohoto kurzu zvažte převod této třídy tak, aby generovala data, která nejlépe odpovídají zamýšlenému schématu indexu.
Velikosti testovacích dávek
Pokud chcete do indexu načíst jeden nebo více dokumentů, Azure AI Search podporuje následující rozhraní API:
Indexování dokumentů v dávkách výrazně zvyšuje výkon indexování. Tyto dávky můžou být až 1 000 dokumentů nebo přibližně 16 MB na dávku.
Určení optimální velikosti dávky pro vaše data je klíčovou součástí optimalizace rychlosti indexování. Optimální velikost dávky ovlivňují dva primární faktory:
- Schéma indexu
- Velikost dat
Vzhledem k tomu, že optimální velikost dávky závisí na indexu a vašich datech, nejlepším přístupem je otestovat různé velikosti dávek, abyste zjistili, jaké výsledky mají pro váš scénář nejrychlejší rychlost indexování.
Následující funkce ukazuje jednoduchý přístup k testování velikostí dávek.
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();
}
Vzhledem k tomu, že ne všechny dokumenty mají stejnou velikost (i když jsou v této ukázce), odhadujeme velikost dat, která odesíláme do vyhledávací služby. Můžete to provést pomocí následující funkce, která nejprve převede objekt na JSON a pak určí jeho velikost v bajtech. Tato technika nám umožňuje určit, které velikosti dávek jsou nejúčinnější z hlediska rychlosti indexování 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;
}
Funkce vyžaduje SearchClient
plus počet pokusů, které chcete otestovat pro každou velikost dávky. Vzhledem k tomu, že pro každou dávku může být proměnlivost časů indexování, vyzkoušejte ve výchozím nastavení každou dávku třikrát, aby výsledky byly statisticky významnější.
await TestBatchSizesAsync(searchClient, numTries: 3);
Když funkci spustíte, měl by se v konzole zobrazit výstup podobný následujícímu příkladu:
Určete, která velikost dávky je nejúčinnější, a tuto velikost dávky použijte v dalším kroku tohoto kurzu. U různých velikostí dávek může dojít k ustálení výkonu v MB/s.
Indexování dat
Teď, když jste identifikovali velikost dávky, kterou chcete použít, je dalším krokem začít indexovat data. Pokud chcete efektivně indexovat data, tato ukázka:
- Používá více vláken nebo pracovních procesů.
- Implementuje exponenciální strategii zpětného odkladu pro opakování.
Odkomentujte řádky 41 až 49 a spusťte program znovu. Při tomto spuštění ukázka vygeneruje a odesílá dávky dokumentů, až 100 000, pokud kód spustíte beze změny parametrů.
Použití více vláken nebo pracovníků
Pokud chcete využít rychlosti indexování služby Azure AI Search, použijte více vláken k souběžnému odesílání dávkových požadavků indexování do služby.
Několik klíčových aspektů může ovlivnit optimální počet vláken. Tuto ukázku a testování můžete upravit s různými počty vláken, abyste zjistili optimální počet vláken pro váš scénář. Pokud ale máte spuštěných několik vláken současně, měli byste být schopni využít výhod většiny zvýšení efektivity.
Při zprovoznění požadavků do vyhledávací služby můžete narazit na stavové kódy HTTP, které značí, že požadavek nebyl plně úspěšný. Během indexování jsou dva běžné stavové kódy HTTP:
- 503 Služba není k dispozici: Tato chyba znamená, že systém je zatížený velkým zatížením a v tuto chvíli nelze vaši žádost zpracovat.
- 207 Multi-Status: Tato chyba znamená, že některé dokumenty byly úspěšné, ale alespoň jeden selhal.
Implementace strategie opakování s exponenciální zpětnou vazbou
Pokud dojde k selhání, měli byste žádosti opakovat pomocí strategie exponenciálního opakování.
.NET SDK služby Azure AI Search automaticky znovu provede pokusy při chybách 503 a ostatních neúspěšných požadavcích, ale měli byste implementovat vlastní logiku pro opakování u 207s. Opensourcové nástroje, jako je Polly , můžou být užitečné ve strategii opakování.
V této ukázce implementujeme vlastní strategii exponenciálního čekacího opakování. Začneme definováním některých proměnných, včetně maxRetryAttempts
a iniciály delay
neúspěšného požadavku.
// 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;
Výsledky operace indexování jsou uloženy v proměnné IndexDocumentResult result
. Tato proměnná vám umožňuje zkontrolovat, zda dokumenty v dávce neuspěly, jak je uvedeno v následujícím příkladu. Pokud dojde k částečnému selhání, vytvoří se nová dávka na základě ID neúspěšných dokumentů.
RequestFailedException
Výjimky by také měly být zachyceny, protože indikují, že žádost selhala úplně, a opakují se.
// 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);
Odtud zabalte kód exponenciálního backoffu do funkce, aby mohla být snadno volána.
Pak se vytvoří další funkce pro správu aktivních vláken. Pro zjednodušení není tato funkce zahrnutá, ale najdete ji v ExponentialBackoff.cs. Funkci můžete volat pomocí následujícího příkazu, kde jsou data, která hotels
chcete nahrát, 1000
je velikost dávky a 8
je počet souběžných vláken.
await ExponentialBackoff.IndexData(indexClient, hotels, 1000, 8);
Při spuštění funkce by se měl zobrazit výstup podobný následujícímu příkladu:
Pokud dávka dokumentů selže, vytiskne se chyba označující selhání a opakování dávky.
[Batch starting at doc 6000 had partial failure]
[Retrying 560 failed documents]
Po dokončení funkce můžete ověřit, že všechny dokumenty byly přidány do indexu.
Prozkoumání indexu
Po dokončení programu můžete prohledávat vyplněný vyhledávací index prostřednictvím kódu programu nebo pomocí Průzkumníka služby Search na webu Azure Portal.
Programově
Existují dvě hlavní možnosti pro kontrolu počtu dokumentů v indexu: rozhraní API Count Documents a rozhraní API pro získání statistik indexu. Obě cesty vyžadují čas na zpracování, takže pokud je počet vrácených dokumentů zpočátku nižší, než očekáváte, nemusíte mít alarm.
Počet dokumentů
Operace Počet dokumentů načte počet dokumentů v indexu vyhledávání.
long indexDocCount = await searchClient.GetDocumentCountAsync();
Získání statistik indexu
Operace Získat statistiku indexu vrátí počet dokumentů pro aktuální index a využití úložiště. Aktualizace statistik indexu trvá déle než počet dokumentů.
var indexStats = await indexClient.GetIndexStatisticsAsync(indexName);
portál Azure
V Azure portálu v levém podokně vyhledejte index optimize-indexing v seznamu Indexy.
Počet dokumentů a velikost úložiště jsou založené na rozhraní API pro získání statistik indexu a aktualizace může trvat několik minut.
Resetování a opětovné spuštění
V počátečních experimentálních fázích vývoje je nejproktičtějším přístupem k iteraci návrhu odstranit objekty z Azure AI Search a umožnit kódu jejich opětovné sestavení. Názvy prostředků jsou jedinečné. Když se objekt odstraní, je možné ho znovu vytvořit se stejným názvem.
Vzorový kód pro tento kurz zkontroluje existující indexy a odstraní je, abyste mohli znovu spustit kód.
Indexy můžete odstranit také pomocí webu Azure Portal.
Čištění prostředků
Když pracujete ve vlastním předplatném, je na konci projektu vhodné odebrat prostředky, které už nepotřebujete. Prostředky, které necháte spuštěné, vás stojí peníze. Prostředky můžete odstraňovat jednotlivě nebo můžete odstranit skupinu prostředků, a odstranit tak celou sadu prostředků najednou.
Prostředky můžete najít a spravovat na webu Azure Portal pomocí odkazu Všechny prostředky nebo skupiny prostředků v levém navigačním podokně.
Další krok
Další informace o indexování velkých objemů dat najdete v následujícím kurzu: