Queryprestaties afstemmen met Azure Cosmos DB

VAN TOEPASSING OP: NoSQL

Azure Cosmos DB biedt een API voor NoSQL voor het uitvoeren van query's op gegevens, zonder dat schema of secundaire indexen nodig zijn. Dit artikel bevat de volgende informatie voor ontwikkelaars:

  • Gedetailleerde informatie over de werking van sql-query's van Azure Cosmos DB
  • Tips en aanbevolen procedures voor queryprestaties
  • Voorbeelden van het gebruik van metrische gegevens over het uitvoeren van SQL-query's om fouten in queryprestaties op te sporen

Over het uitvoeren van SQL-query's

In Azure Cosmos DB-gegevens worden opgeslagen in containers, die kunnen groeien tot elke opslaggrootte of aanvraagdoorvoer. Azure Cosmos DB schaalt gegevens naadloos over fysieke partities onder de dekking om gegevensgroei of toenames in ingerichte doorvoer af te handelen. U kunt SQL-query's uitgeven aan elke container met behulp van de REST API of een van de ondersteunde SQL SDK's.

Een kort overzicht van partitionering: u definieert een partitiesleutel zoals 'plaats', waarmee wordt bepaald hoe gegevens worden verdeeld over fysieke partities. Gegevens die behoren tot één partitiesleutel (bijvoorbeeld 'plaats' == 'Seattle') worden opgeslagen in een fysieke partitie en één fysieke partitie kan gegevens van meerdere partitiesleutels opslaan. Wanneer een partitie de opslaglimiet bereikt, splitst de service de partitie naadloos op in twee nieuwe partities. Gegevens worden gelijkmatig verdeeld over de nieuwe partities, waardoor alle gegevens voor één partitiesleutel bij elkaar blijven. Omdat partities tijdelijk zijn, gebruiken de API's een abstractie van een partitiesleutelbereik, wat de bereiken van partitiesleutel-hashes aangeeft.

Wanneer u een query naar Azure Cosmos DB uitvoert, voert de SDK de volgende logische stappen uit:

  • Parseert de SQL-query om het uitvoeringsplan van de query te bepalen.
  • Als de query een filter bevat op basis van de partitiesleutel, zoals SELECT * FROM c WHERE c.city = "Seattle", wordt deze gerouteerd naar één partitie. Als de query geen filter op de partitiesleutel heeft, wordt deze uitgevoerd in alle partities en worden de resultaten van elke partitie samengevoegd aan de clientzijde.
  • De query wordt uitgevoerd binnen elke partitie in reeks of parallel, op basis van clientconfiguratie. Binnen elke partitie kan de query een of meer retouren maken, afhankelijk van de complexiteit van de query, het geconfigureerde paginaformaat en de ingerichte doorvoer van de verzameling. Elke uitvoering retourneert het aantal aanvraageenheden dat wordt gebruikt door queryuitvoerings- en queryuitvoeringsstatistieken.
  • De SDK voert een samenvatting uit van de queryresultaten in meerdere partities. Als de query bijvoorbeeld een ORDER BY tussen partities omvat, worden resultaten van afzonderlijke partities samengevoegd om resultaten in globaal gesorteerde volgorde te retourneren. Als de query een aggregatie is zoals COUNT, worden de aantallen van afzonderlijke partities opgeteld om het totale aantal te produceren.

De SDK's bieden verschillende opties voor het uitvoeren van query's. In .NET zijn deze opties bijvoorbeeld beschikbaar in de QueryRequestOptions klasse. In de volgende tabel worden deze opties beschreven en hoe deze van invloed zijn op de uitvoeringstijd van query's.

Optie Omschrijving
EnableScanInQuery Alleen van toepassing als indexering voor het aangevraagde filterpad is uitgeschakeld. Moet zijn ingesteld op true als u zich hebt afgemeld voor indexering en query's wilt uitvoeren met behulp van een volledige scan.
MaxItemCount Het maximum aantal items dat per retour naar de server moet worden geretourneerd. U kunt deze instellen op -1 om de server het aantal items te laten beheren dat moet worden geretourneerd.
MaxBufferedItemCount Het maximum aantal items dat kan worden gebufferd aan de clientzijde tijdens parallelle uitvoering van query's. Een positieve eigenschapswaarde beperkt het aantal gebufferde items tot de ingestelde waarde. U kunt deze instellen op minder dan 0, zodat het systeem automatisch bepaalt hoeveel items er moeten worden gebufferd.
MaxConcurrency Hiermee wordt het aantal gelijktijdige bewerkingen aan de clientzijde tijdens parallelle uitvoering van query's ophaalt of ingesteld. Een positieve eigenschapswaarde beperkt het aantal gelijktijdige bewerkingen tot de ingestelde waarde. U kunt deze instellen op minder dan 0, zodat het systeem automatisch bepaalt hoeveel gelijktijdige bewerkingen moeten worden uitgevoerd.
PopulateIndexMetrics Hiermee kunt u het verzamelen van metrische indexgegevens begrijpen hoe de query-engine bestaande indexen heeft gebruikt en hoe deze potentiële nieuwe indexen kan gebruiken. Met deze optie wordt overhead in rekening gebracht, dus deze moet alleen worden ingeschakeld wanneer trage query's worden opgespoord.
ResponseContinuationTokenLimitInKb U kunt de maximale grootte van het vervolgtoken beperken dat door de server wordt geretourneerd. Mogelijk moet u dit instellen als uw toepassingshost limieten heeft voor de headergrootte van het antwoord, maar dit kan de totale duur en de verbruikte RU's voor de query verhogen.

Hier volgt bijvoorbeeld een query op een container die is gepartitioneerd /city met behulp van de .NET SDK:

QueryDefinition query = new QueryDefinition("SELECT * FROM c WHERE c.city = 'Seattle'");
QueryRequestOptions options = new QueryRequestOptions()
{
    MaxItemCount = -1,
    MaxBufferedItemCount = -1,
    MaxConcurrency = -1,
    PopulateIndexMetrics = true
};
FeedIterator<dynamic> feedIterator = container.GetItemQueryIterator<dynamic>(query);

FeedResponse<dynamic> feedResponse = await feedIterator.ReadNextAsync();

Elke queryuitvoering komt overeen met een REST API POST met headers die zijn ingesteld voor de queryaanvraagopties en de SQL-query in de hoofdtekst. Zie Resources opvragen met behulp van de REST API voor meer informatie over de REST API-aanvraagheaders en -opties.

Aanbevolen procedures voor queryprestaties

De volgende factoren hebben meestal het grootste effect op de prestaties van Azure Cosmos DB-query's. In dit artikel gaan we dieper in op elk van deze factoren.

Factor Tip
Ingerichte doorvoer Meet RU per query en zorg ervoor dat u de vereiste ingerichte doorvoer voor uw query's hebt.
Partitionering en partitiesleutels Geef de voorkeur aan query's met de partitiesleutelwaarde in de filtercomponent voor lage latentie.
SDK- en queryopties Volg best practices voor SDK, zoals directe connectiviteit en stem queryuitvoeringsopties aan de clientzijde af.
Netwerklatentie Voer uw toepassing uit in dezelfde regio als uw Azure Cosmos DB-account, waar mogelijk om de latentie te verminderen.
Indexeringsbeleid Zorg ervoor dat u beschikt over de vereiste indexeringspaden/-beleid voor de query.
Metrische gegevens over uitvoering van query's Analyseer de metrische gegevens over de uitvoering van query's om mogelijke herschrijfbewerkingen van query- en gegevensshapes te identificeren.

Ingerichte doorvoer

In Azure Cosmos DB maakt u containers met gegevens, elk met gereserveerde doorvoer uitgedrukt in aanvraageenheden (RU) per seconde. Een leesbewerking van een document van 1 kB is één RU en elke bewerking (inclusief query's) wordt genormaliseerd tot een vast aantal RU's op basis van de complexiteit ervan. Als u bijvoorbeeld 1000 RU/s hebt ingericht voor uw container en u een query hebt die SELECT * FROM c WHERE c.city = 'Seattle' 5 RU's verbruikt, kunt u (1000 RU/s) / (5 RU/query) = 200 van deze query's per seconde uitvoeren.

Als u meer dan 200 query's per seconde verzendt (of een aantal andere bewerkingen die alle ingerichte RU's verzadigen), begint de service met het beperken van binnenkomende aanvragen. De SDK's verwerken automatisch snelheidsbeperking door een back-off/nieuwe poging uit te voeren. Daarom ziet u mogelijk een hogere latentie voor deze query's. Als u de ingerichte doorvoer verhoogt naar de vereiste waarde, verbetert u de latentie en doorvoer van uw query.

Zie Aanvraageenheden voor meer informatie over aanvraageenheden.

Partitionering en partitiesleutels

Met Azure Cosmos DB worden de volgende scenario's voor het lezen van gegevens gerangschikt op basis van wat doorgaans het snelst/meest efficiënt is tot de traagste/minst efficiënte.

  • GET op één partitiesleutel en item-id, ook wel een punt gelezen
  • Query's uitvoeren met een filtercomponent op één partitiesleutel
  • Query's uitvoeren met een gelijkheids- of bereikfiltercomponent voor een eigenschap
  • Query zonder filters

Query's die op alle partities moeten worden uitgevoerd, hebben een hogere latentie en kunnen hogere RU's verbruiken. Omdat elke partitie automatische indexering heeft voor alle eigenschappen, kan de query in dit geval efficiënt worden verwerkt vanuit de index. U kunt query's die partities omvatten sneller maken met behulp van de opties voor parallelle uitvoering.

Zie Partitionering in Azure Cosmos DB voor meer informatie over partitionering en partitiesleutels.

SDK- en queryopties

Zie tips voor queryprestaties en prestatietests voor het verkrijgen van de beste prestaties aan de clientzijde van Azure Cosmos DB met behulp van onze SDK's.

Netwerklatentie

Zie de wereldwijde distributie van Azure Cosmos DB voor informatie over het instellen van wereldwijde distributie en het maken van verbinding met de dichtstbijzijnde regio. Netwerklatentie heeft een aanzienlijk effect op queryprestaties wanneer u meerdere retouren moet maken of een grote resultatenset uit de query moet ophalen.

U kunt metrische gegevens over queryuitvoering gebruiken om de uitvoeringstijd van de server van query's op te halen, zodat u onderscheid kunt maken tussen de tijd die is besteed aan de uitvoering van query's vanaf de tijd die is besteed aan netwerkoverdracht.

Indexeringsbeleid

Zie het configureren van indexeringsbeleid voor het indexeren van paden, soorten en modi en hoe deze van invloed zijn op de uitvoering van query's. Azure Cosmos DB past standaard automatische indexering toe op alle gegevens en maakt gebruik van bereikindexen voor tekenreeksen en getallen, wat effectief is voor gelijkheidsquery's. Voor scenario's voor invoegen met hoge prestaties kunt u overwegen paden uit te sluiten om de RU-kosten voor elke invoegbewerking te verlagen.

U kunt de metrische indexgegevens gebruiken om te bepalen welke indexen worden gebruikt voor elke query en of er ontbrekende indexen zijn die de queryprestaties zouden verbeteren.

Metrische gegevens over uitvoering van query's

Gedetailleerde metrische gegevens worden geretourneerd voor elke queryuitvoering in de diagnostische gegevens voor de aanvraag. Deze metrische gegevens beschrijven waar de tijd wordt besteed tijdens het uitvoeren van query's en geavanceerde probleemoplossing inschakelen.

Meer informatie over het ophalen van de metrische querygegevens.

Metric Eenheid Beschrijving
TotalTime milliseconden Totale uitvoeringstijd van query's
DocumentLoadTime milliseconden Tijd besteed aan het laden van documenten
DocumentWriteTime milliseconden Tijd besteed aan het schrijven en serialiseren van de uitvoerdocumenten
IndexLookupTime milliseconden Tijd besteed aan fysieke indexlaag
QueryPreparationTime milliseconden Tijd besteed aan het voorbereiden van query's
RuntimeExecutionTime milliseconden Totale uitvoeringstijd van queryruntime
VMExecutionTime milliseconden Tijd die is besteed aan queryruntime voor het uitvoeren van de query
OutputDocumentCount aantal Aantal uitvoerdocumenten in de resultatenset
OutputDocumentSize aantal Totale grootte van uitvoerdocumenten in bytes
RetrievedDocumentCount aantal Totaal aantal opgehaalde documenten
RetrievedDocumentSize bytes Totale grootte van opgehaalde documenten in bytes
IndexHitRatio verhouding [0,1] Verhouding van het aantal documenten dat door het filter wordt vergeleken met het aantal geladen documenten

De client-SDK's kunnen intern meerdere queryaanvragen uitvoeren om de query binnen elke partitie te verwerken. De client voert meer dan één aanroep per partitie uit als de totale resultaten de aanvraagoptie maximum aantal items overschrijden, als de query de ingerichte doorvoer voor de partitie overschrijdt, als de nettolading van de query de maximale grootte per pagina bereikt of als de query de door het systeem toegewezen time-outlimiet bereikt. Elke gedeeltelijke queryuitvoering retourneert metrische querygegevens voor die pagina.

Hier volgen enkele voorbeeldquery's en hoe u enkele metrische gegevens interpreteert die worden geretourneerd door de queryuitvoering:

Query’s uitvoeren Voorbeeld van metrische gegevens Beschrijving
SELECT TOP 100 * FROM c "RetrievedDocumentCount": 101 Het aantal opgehaalde documenten is 100+1 om overeen te komen met de TOP-component. Querytijd wordt meestal besteed WriteOutputTime aan en DocumentLoadTime omdat het een scan is.
SELECT TOP 500 * FROM c "RetrievedDocumentCount": 501 RetrievedDocumentCount is nu hoger (500+1 die overeenkomt met de TOP-component).
SELECT * FROM c WHERE c.N = 55 "IndexLookupTime": "00:00:00.0009500" Ongeveer 0,9 ms wordt besteed in IndexLookupTime voor een sleutelzoekactie, omdat het een indexzoekactie /N/?op is.
SELECT * FROM c WHERE c.N > 55 "IndexLookupTime": "00:00:00.0017700" Iets meer tijd (1,7 ms) besteed in IndexLookupTime via een bereikscan, omdat het een indexzoekactie /N/?op is.
SELECT TOP 500 c.N FROM c "IndexLookupTime": "00:00:00.0017700" Dezelfde tijd die is besteed aan DocumentLoadTime eerdere query's, maar lager DocumentWriteTime omdat we slechts één eigenschap projecteren.
SELECT TOP 500 udf.toPercent(c.N) FROM c "RuntimeExecutionTime": "00:00:00.2136500" Ongeveer 213 ms wordt besteed aan RuntimeExecutionTime het uitvoeren van de UDF op elke waarde van c.N.
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(c.Name, 'Den') "IndexLookupTime": "00:00:00.0006400", "RuntimeExecutionTime": "00:00:00.0074100" Ongeveer 0,6 ms wordt besteed IndexLookupTime aan /Name/?. De meeste uitvoeringstijd van de query (~7 ms) in RuntimeExecutionTime.
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(LOWER(c.Name), 'den') "IndexLookupTime": "00:00:00", "RetrievedDocumentCount": 2491, "OutputDocumentCount": 500 De query wordt uitgevoerd als een scan omdat er LOWER500 van de 2491 opgehaalde documenten worden geretourneerd.

Volgende stappen