Justera frågeprestanda med Azure Cosmos DB

GÄLLER FÖR: NoSQL

Azure Cosmos DB tillhandahåller ett API för NoSQL för att fråga efter data, utan schema eller sekundära index. Den här artikeln innehåller följande information för utvecklare:

  • Information på hög nivå om hur SQL-frågekörning i Azure Cosmos DB fungerar
  • Information om frågeförfrågnings- och svarshuvuden och klient-SDK-alternativ
  • Tips och metodtips för frågeprestanda
  • Exempel på hur du använder SQL-körningsstatistik för att felsöka frågeprestanda

Om SQL-frågekörning

I Azure Cosmos DB lagrar du data i containrar, som kan växa till valfri lagringsstorlek eller begära dataflöde. Azure Cosmos DB skalar sömlöst data över fysiska partitioner under täcket för att hantera datatillväxt eller öka etablerat dataflöde. Du kan utfärda SQL-frågor till valfri container med hjälp av REST-API:et eller någon av de SQL SDK:er som stöds.

En kort översikt över partitionering: du definierar en partitionsnyckel som "stad", som avgör hur data delas mellan fysiska partitioner. Data som tillhör en enda partitionsnyckel (till exempel "stad" == "Seattle") lagras i en fysisk partition, men vanligtvis har en enda fysisk partition flera partitionsnycklar. När en partition når sin lagringsstorlek delar tjänsten sömlöst upp partitionen i två nya partitioner och delar partitionsnyckeln jämnt över dessa partitioner. Eftersom partitioner är tillfälliga använder API:erna en abstraktion av ett "partitionsnyckelintervall", som anger intervallen för partitionsnyckel-hashvärden.

När du utfärdar en fråga till Azure Cosmos DB utför SDK:et följande logiska steg:

  • Parsa SQL-frågan för att fastställa frågekörningsplanen.
  • Om frågan innehåller ett filter mot partitionsnyckeln, till exempel SELECT * FROM c WHERE c.city = "Seattle", dirigeras den till en enda partition. Om frågan inte har något filter på partitionsnyckeln körs den i alla partitioner och resultatet sammanfogas på klientsidan.
  • Frågan körs inom varje partition i serie eller parallell, baserat på klientkonfiguration. I varje partition kan frågan göra en eller flera turer beroende på frågekomplexiteten, den konfigurerade sidstorleken och det etablerade dataflödet för samlingen. Varje körning returnerar antalet enheter för begäranden som förbrukas av frågekörning och eventuellt frågekörningsstatistik.
  • SDK:et utför en sammanfattning av frågeresultaten mellan partitioner. Om frågan till exempel omfattar en ORDER BY mellan partitioner sammanfogas resultat från enskilda partitioner för att returnera resultat i globalt sorterad ordning. Om frågan är en aggregering som COUNT, summeras antalet från enskilda partitioner för att generera det totala antalet.

SDK:erna innehåller olika alternativ för frågekörning. I .NET är dessa alternativ till exempel tillgängliga i FeedOptions klassen . I följande tabell beskrivs de här alternativen och hur de påverkar frågekörningstiden.

Alternativ Beskrivning
EnableCrossPartitionQuery Måste anges till true för alla frågor som måste köras över mer än en partition. Det här är en explicit flagga som gör att du kan göra medvetna prestandaavvägningar under utvecklingstiden.
EnableScanInQuery Måste anges till sant om du har valt bort indexering, men ändå vill köra frågan via en genomsökning. Gäller endast om indexering för den begärda filtersökvägen är inaktiverad.
MaxItemCount Det maximala antalet objekt som ska returneras per tur och retur till servern. Genom att ange till -1 kan du låta servern hantera antalet objekt. Eller så kan du sänka det här värdet för att bara hämta ett litet antal objekt per tur och retur.
MaxBufferedItemCount Det här är ett alternativ på klientsidan som används för att begränsa minnesförbrukningen när du utför ORDER BY mellan partitioner. Ett högre värde hjälper till att minska svarstiden för sortering mellan partitioner.
MaxDegreeOfParallelism Hämtar eller anger antalet samtidiga åtgärder som körs på klientsidan under parallell frågekörning i Azure Cosmos DB-databastjänsten. Ett positivt egenskapsvärde begränsar antalet samtidiga åtgärder till det angivna värdet. Om den är inställd på mindre än 0 bestämmer systemet automatiskt antalet samtidiga åtgärder som ska köras.
PopulateQueryMetrics Möjliggör detaljerad loggning av statistik över tid i olika faser av frågekörning som kompileringstid, indexlooptid och dokumentinläsningstid. Du kan dela utdata från frågestatistik med Azure Support för att diagnostisera problem med frågeprestanda.
RequestContinuation Du kan återuppta frågekörningen genom att skicka in den täckande fortsättningstoken som returneras av valfri fråga. Fortsättningstoken kapslar in allt tillstånd som krävs för frågekörning.
ResponseContinuationTokenLimitInKb Du kan begränsa den maximala storleken på fortsättningstoken som returneras av servern. Du kan behöva ange detta om programvärden har gränser för svarshuvudets storlek. Om du anger detta kan den totala varaktigheten och RU:er som används för frågan öka.

Låt oss till exempel ta en exempelfråga på partitionsnyckeln som begärs i en samling med /city som partitionsnyckel och etableras med 100 000 RU/s dataflöde. Du begär den här frågan med hjälp av CreateDocumentQuery<T> i .NET på följande sätt:

IDocumentQuery<dynamic> query = client.CreateDocumentQuery(
    UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName), 
    "SELECT * FROM c WHERE c.city = 'Seattle'", 
    new FeedOptions 
    { 
        PopulateQueryMetrics = true, 
        MaxItemCount = -1, 
        MaxDegreeOfParallelism = -1, 
        EnableCrossPartitionQuery = true 
    }).AsDocumentQuery();

FeedResponse<dynamic> result = await query.ExecuteNextAsync();

SDK-kodfragmentet som visas ovan motsvarar följande REST API-begäran:

POST https://arramacquerymetrics-westus.documents.azure.com/dbs/db/colls/sample/docs HTTP/1.1
x-ms-continuation: 
x-ms-documentdb-isquery: True
x-ms-max-item-count: -1
x-ms-documentdb-query-enablecrosspartition: True
x-ms-documentdb-query-parallelizecrosspartitionquery: True
x-ms-documentdb-query-iscontinuationexpected: True
x-ms-documentdb-populatequerymetrics: True
x-ms-date: Tue, 27 Jun 2017 21:52:18 GMT
authorization: type%3dmaster%26ver%3d1.0%26sig%3drp1Hi83Y8aVV5V6LzZ6xhtQVXRAMz0WNMnUuvriUv%2b4%3d
x-ms-session-token: 7:8,6:2008,5:8,4:2008,3:8,2:2008,1:8,0:8,9:8,8:4008
Cache-Control: no-cache
x-ms-consistency-level: Session
User-Agent: documentdb-dotnet-sdk/1.14.1 Host/32-bit MicrosoftWindowsNT/6.2.9200.0
x-ms-version: 2017-02-22
Accept: application/json
Content-Type: application/query+json
Host: arramacquerymetrics-westus.documents.azure.com
Content-Length: 52
Expect: 100-continue

{"query":"SELECT * FROM c WHERE c.city = 'Seattle'"}

Varje frågekörningssida motsvarar ett REST API POST med Accept: application/query+json huvudet och SQL-frågan i brödtexten. Varje fråga gör en eller flera turer till servern med token x-ms-continuation som upprepas mellan klienten och servern för att återuppta körningen. Konfigurationsalternativen i FeedOptions skickas till servern i form av begärandehuvuden. Motsvarar till x-ms-max-item-countexempel MaxItemCount .

Begäran returnerar följande (trunkerade för läsbarhet) svar:

HTTP/1.1 200 Ok
Cache-Control: no-store, no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
Strict-Transport-Security: max-age=31536000
x-ms-last-state-change-utc: Tue, 27 Jun 2017 21:01:57.561 GMT
x-ms-resource-quota: documentSize=10240;documentsSize=10485760;documentsCount=-1;collectionSize=10485760;
x-ms-resource-usage: documentSize=1;documentsSize=884;documentsCount=2000;collectionSize=1408;
x-ms-item-count: 2000
x-ms-schemaversion: 1.3
x-ms-alt-content-path: dbs/db/colls/sample
x-ms-content-path: +9kEANVq0wA=
x-ms-xp-role: 1
x-ms-documentdb-query-metrics: totalExecutionTimeInMs=33.67;queryCompileTimeInMs=0.06;queryLogicalPlanBuildTimeInMs=0.02;queryPhysicalPlanBuildTimeInMs=0.10;queryOptimizationTimeInMs=0.00;VMExecutionTimeInMs=32.56;indexLookupTimeInMs=0.36;documentLoadTimeInMs=9.58;systemFunctionExecuteTimeInMs=0.00;userFunctionExecuteTimeInMs=0.00;retrievedDocumentCount=2000;retrievedDocumentSize=1125600;outputDocumentCount=2000;writeOutputTimeInMs=18.10;indexUtilizationRatio=1.00
x-ms-request-charge: 604.42
x-ms-serviceversion: version=1.14.34.4
x-ms-activity-id: 0df8b5f6-83b9-4493-abda-cce6d0f91486
x-ms-session-token: 2:2008
x-ms-gatewayversion: version=1.14.33.2
Date: Tue, 27 Jun 2017 21:59:49 GMT

Nyckelsvarshuvudena som returneras från frågan innehåller följande:

Alternativ Beskrivning
x-ms-item-count Antalet objekt som returneras i svaret. Detta beror på det angivna x-ms-max-item-countantalet objekt som kan passas in i den maximala svarsnyttolastens storlek, det etablerade dataflödet och frågekörningstiden.
x-ms-continuation: Fortsättningstoken för att återuppta körningen av frågan, om ytterligare resultat är tillgängliga.
x-ms-documentdb-query-metrics Frågestatistiken för körningen. Det här är en avgränsad sträng som innehåller statistik över tid i de olika faserna av frågekörningen. Returneras om x-ms-documentdb-populatequerymetrics är inställt på True.
x-ms-request-charge Antalet enheter för begäranden som används av frågan.

Mer information om REST API-begärandehuvuden och alternativ finns i Fråga efter resurser med hjälp av REST-API:et.

Metodtips för frågeprestanda

Följande är de vanligaste faktorerna som påverkar Azure Cosmos DB-frågeprestanda. Vi går djupare in på vart och ett av dessa ämnen i den här artikeln.

Faktor Tips
Etablerat dataflöde Mät RU per fråga och se till att du har det etablerade dataflödet som krävs för dina frågor.
Partitionering och partitionsnycklar Prioritera frågor med partitionsnyckelvärdet i filtersatsen för låg svarstid.
SDK och frågealternativ Följ SDK:s metodtips som direktanslutning och finjustera körningsalternativ för frågor på klientsidan.
Indexeringsprincip Kontrollera att du har de indexeringssökvägar/principer som krävs för frågan.
Frågekörningsmått Analysera frågekörningsmåtten för att identifiera potentiella omskrivningar av fråge- och dataformer.

Etablerat dataflöde

I Azure Cosmos DB skapar du containrar med data, var och en med reserverat dataflöde uttryckt i enheter för programbegäran (RU) per sekund. En läsning av ett 1 KB-dokument är 1 RU och varje åtgärd (inklusive frågor) normaliseras till ett fast antal RU:er baserat på dess komplexitet. Om du till exempel har 1 000 RU/s etablerade för containern och du har en fråga som använder SELECT * FROM c WHERE c.city = 'Seattle' 5 RU:er kan du utföra (1 000 RU/s) / (5 RU/query) = 200 frågor/s sådana frågor per sekund.

Om du skickar mer än 200 frågor per sekund startar tjänsten hastighetsbegränsning av inkommande begäranden över 200/s. SDK:erna hanterar det här fallet automatiskt genom att utföra en backoff/ett nytt försök. Därför kan du se en högre svarstid för dessa frågor. Om du ökar det etablerade dataflödet till det nödvändiga värdet förbättras frågesvarstiden och dataflödet.

Mer information om enheter för programbegäran finns i Enheter för begäran.

Partitionering och partitionsnycklar

Med Azure Cosmos DB utförs vanligtvis frågor i följande ordning från snabbast/mest effektivt till långsammare/mindre effektivt.

  • GET på en enda partitionsnyckel och objektnyckel
  • Fråga med en filtersats på en enda partitionsnyckel
  • Fråga utan likhets- eller intervallfiltersats på någon egenskap
  • Fråga utan filter

Frågor som behöver konsultera alla partitioner behöver högre svarstid och kan använda högre RU:er. Eftersom varje partition har automatisk indexering mot alla egenskaper kan frågan hanteras effektivt från indexet i det här fallet. Du kan göra frågor som sträcker sig över partitioner snabbare med hjälp av parallellitetsalternativen.

Mer information om partitionering och partitionsnycklar finns i Partitionering i Azure Cosmos DB.

SDK och frågealternativ

Se Frågeprestandatips och Prestandatestning för hur du får bästa prestanda på klientsidan från Azure Cosmos DB med hjälp av våra SDK:er.

Svarstid för nätverk

Se Global distribution i Azure Cosmos DB för hur du konfigurerar global distribution och ansluter till den närmaste regionen. Nätverksfördröjningen har en betydande inverkan på frågeprestanda när du behöver göra flera turer eller hämta en stor resultatuppsättning från frågan.

Avsnittet om frågekörningsmått förklarar hur du hämtar serverkörningstiden för frågor ( totalExecutionTimeInMs), så att du kan skilja mellan tid som ägnas åt frågekörning och tid under nätverksöverföring.

Indexeringsprincip

Se Konfigurera indexeringsprincip för indexering av sökvägar, typer och lägen och hur de påverkar frågekörning. Indexeringsprincipen använder som standard intervallindexering för strängar, vilket är effektivt för likhetsfrågor. Om du behöver intervallfrågor för strängar rekommenderar vi att du anger indextypen Intervall för alla strängar.

Som standard tillämpar Azure Cosmos DB automatisk indexering på alla data. För scenarier med högpresterande infogning bör du överväga att undanta sökvägar eftersom detta minskar RU-kostnaden för varje infogningsåtgärd.

Frågekörningsmått

Du kan hämta detaljerade mått för frågekörning genom att skicka in det valfria x-ms-documentdb-populatequerymetrics huvudet (FeedOptions.PopulateQueryMetrics i .NET SDK). Värdet som returneras i x-ms-documentdb-query-metrics har följande nyckel/värde-par avsedda för avancerad felsökning av frågekörning.

IDocumentQuery<dynamic> query = client.CreateDocumentQuery(
    UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName), 
    "SELECT * FROM c WHERE c.city = 'Seattle'", 
    new FeedOptions 
    { 
        PopulateQueryMetrics = true, 
    }).AsDocumentQuery();

FeedResponse<dynamic> result = await query.ExecuteNextAsync();

// Returns metrics by partition key range Id
IReadOnlyDictionary<string, QueryMetrics> metrics = result.QueryMetrics;

Metric Enhet Beskrivning
totalExecutionTimeInMs millisekunder Körningstid för frågor
queryCompileTimeInMs millisekunder Frågekompileringstid
queryLogicalPlanBuildTimeInMs millisekunder Dags att skapa en logisk frågeplan
queryPhysicalPlanBuildTimeInMs millisekunder Dags att skapa en fysisk frågeplan
queryOptimizationTimeInMs millisekunder Tid som ägnas åt att optimera frågan
VMExecutionTimeInMs millisekunder Tid som ägnas åt frågekörning
indexLookupTimeInMs millisekunder Tid i fysiskt indexskikt
documentLoadTimeInMs millisekunder Tid som ägnas åt att läsa in dokument
systemFunctionExecuteTimeInMs millisekunder Total tid för körning av systemfunktioner (inbyggda) i millisekunder
userFunctionExecuteTimeInMs millisekunder Total tid för körning av användardefinierade funktioner i millisekunder
retrievedDocumentCount count Totalt antal hämtade dokument
retrievedDocumentSize Byte Total storlek för hämtade dokument i byte
outputDocumentCount count Antal utdatadokument
writeOutputTimeInMs millisekunder Tid som ägnas åt att skriva utdata i millisekunder
indexUtilizationRatio förhållande (<=1) Förhållandet mellan antalet dokument som matchas av filtret och antalet inlästa dokument

Klient-SDK:erna kan internt utföra flera frågeåtgärder för att hantera frågan inom varje partition. Klienten gör fler än ett anrop per partition om det totala resultatet överskrider x-ms-max-item-count, om frågan överskrider det etablerade dataflödet för partitionen, eller om frågenyttolasten når maximal storlek per sida eller om frågan når den systemallokerade tidsgränsen. Varje partiell frågekörning returnerar en x-ms-documentdb-query-metrics för den sidan.

Här är några exempelfrågor och hur du tolkar några av måtten som returneras från frågekörning:

Söka i data Exempelmått Beskrivning
SELECT TOP 100 * FROM c "RetrievedDocumentCount": 101 Antalet dokument som hämtas är 100+1 för att matcha TOP-satsen. Frågetiden ägnas främst åt WriteOutputTime och DocumentLoadTime eftersom det är en genomsökning.
SELECT TOP 500 * FROM c "RetrievedDocumentCount": 501 RetrievedDocumentCount är nu högre (500+1 för att matcha TOP-satsen).
SELECT * FROM c WHERE c.N = 55 "IndexLookupTime": "00:00:00.0009500" Cirka 0,9 ms spenderas i IndexLookupTime för en nyckelsökning, eftersom det är en indexsökning på /N/?.
SELECT * FROM c WHERE c.N > 55 "IndexLookupTime": "00:00:00.0017700" Lite mer tid (1,7 ms) i IndexLookupTime över en intervallgenomsökning, eftersom det är en indexsökning på /N/?.
SELECT TOP 500 c.N FROM c "IndexLookupTime": "00:00:00.0017700" Samma tid som lagts på DocumentLoadTime som tidigare frågor, men lägre WriteOutputTime eftersom vi bara projicerar en egenskap.
SELECT TOP 500 udf.toPercent(c.N) FROM c "UserDefinedFunctionExecutionTime": "00:00:00.2136500" Cirka 213 ms används för UserDefinedFunctionExecutionTime att köra UDF på varje värde av c.N.
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(c.Name, 'Den') "IndexLookupTime": "00:00:00.0006400", "SystemFunctionExecutionTime": "00:00:00.0074100" Cirka 0,6 ms spenderas i IndexLookupTime/Name/?. Merparten av frågekörningstiden (~7 ms) i SystemFunctionExecutionTime.
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(LOWER(c.Name), 'den') "IndexLookupTime": "00:00:00", "RetrievedDocumentCount": 2491, "OutputDocumentCount": 500 Frågan utförs som en genomsökning eftersom den använder LOWERoch 500 av 2 491 hämtade dokument returneras.

Nästa steg