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-count
exempel 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-count antalet 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 på /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 LOWER och 500 av 2 491 hämtade dokument returneras. |
Nästa steg
- Mer information om sql-frågeoperatorer och nyckelord som stöds finns i SQL-fråga.
- Mer information om enheter för programbegäran finns i enheter för begäran.
- Mer information om indexeringsprincip finns i Indexeringsprincip