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 att behöva 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örningen i Azure Cosmos DB fungerar
  • Tips och metodtips för frågeprestanda
  • Exempel på hur du använder SQL-frågekörningsmått för att felsöka frågeprestanda

Om SQL-frågekörning

I Azure Cosmos DB lagras data i containrar som kan växa till valfri lagringsstorlek eller dataflöde för begäranden. Azure Cosmos DB skalar sömlöst data mellan fysiska partitioner under täcket för att hantera datatillväxt eller ökningar av 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 och en enskild fysisk partition kan lagra data från flera partitionsnycklar. När en partition når sin lagringsgräns delar tjänsten sömlöst upp partitionen i två nya partitioner. Data fördelas jämnt över de nya partitionerna och håller ihop alla data för en enda partitionsnyckel. Eftersom partitioner är tillfälliga använder API:erna en abstraktion av ett partitionsnyckelintervall, som anger intervallen för partitionsnyckelshashvä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 resultaten från varje partition sammanfogas på klientsidan.
  • Frågan körs inom varje partition i serie eller parallell, baserat på klientkonfiguration. Inom varje partition kan frågan göra en eller flera rundturer 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örnings- och frågekörningsstatistik.
  • SDK utför en sammanfattning av frågeresultaten mellan partitioner. Om frågan till exempel omfattar 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 COUNTsummeras 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 QueryRequestOptions klassen. I följande tabell beskrivs de här alternativen och hur de påverkar frågekörningstiden.

Alternativ Description
EnableScanInQuery Gäller endast om indexering för den begärda filtersökvägen är inaktiverad. Måste anges till true om du har valt bort indexering och vill köra frågor med en fullständig genomsökning.
MaxItemCount Det maximala antalet objekt som ska returneras per tur och retur till servern. Du kan ange -1 för att låta servern hantera antalet objekt som ska returneras.
MaxBufferedItemCount Det maximala antalet objekt som kan bufferas på klientsidan under parallell frågekörning. Ett positivt egenskapsvärde begränsar antalet buffrade objekt till det angivna värdet. Du kan ange det till mindre än 0 så att systemet automatiskt kan bestämma hur många objekt som ska buffas.
MaxConcurrency Hämtar eller anger antalet samtidiga åtgärder som körs på klientsidan under parallell frågekörning. Ett positivt egenskapsvärde begränsar antalet samtidiga åtgärder till det angivna värdet. Du kan ange det till mindre än 0 så att systemet automatiskt kan bestämma antalet samtidiga åtgärder som ska köras.
PopulateIndexMetrics Gör det möjligt för insamling av indexmått att förstå hur frågemotorn använde befintliga index och hur den kan använda potentiella nya index. Det här alternativet medför kostnader, så det bör bara aktiveras när långsamma frågor felsöks.
ResponseContinuationTokenLimitInKb Du kan begränsa den maximala storleken på den fortsättningstoken som returneras av servern. Du kan behöva ange detta om programvärden har gränser för svarshuvudets storlek, men det kan öka den totala varaktigheten och ru:erna som förbrukas för frågan.

Här är till exempel en fråga på en container som partitionerats med hjälp av /city .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();

Varje frågekörning motsvarar ett REST-API POST med rubriker som angetts för frågebegärandealternativen och SQL-frågan i brödtexten. 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 faktorer har vanligtvis störst effekt på Azure Cosmos DB-frågeprestanda. Vi går djupare in på var och en av dessa faktorer i den här artikeln.

Faktor Dricks
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.
Partitionerings- och partitionsnycklar Prioritera frågor med partitionsnyckelvärdet i filtersatsen för låg svarstid.
SDK och frågealternativ Följ metodtipsen för SDK som direktanslutning och justera körningsalternativ för frågor på klientsidan.
Svarstid för nätverk Kör ditt program i samma region som ditt Azure Cosmos DB-konto där det är möjligt för att minska svarstiden.
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 begäran (RU) per sekund. En läsning av ett 1 KB-dokument är en 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 SELECT * FROM c WHERE c.city = 'Seattle' använder 5 RU:er kan du köra (1 000 RU/s) / (5 RU/query) = 200 av dessa frågor per sekund.

Om du skickar mer än 200 frågor per sekund (eller några andra åtgärder som mättar alla etablerade RU:er) startar tjänsten hastighetsbegränsning av inkommande begäranden. SDK:erna hanterar automatiskt hastighetsbegränsning genom att utföra en backoff/ett nytt försök. Därför kanske du märker 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 begäran finns i Enheter för begäran.

Partitionerings- och partitionsnycklar

Med Azure Cosmos DB sorteras följande scenarier för att läsa data från det som vanligtvis är snabbast/mest effektivt till det långsammaste/minst effektiva.

  • GET på en enda partitionsnyckel och objekt-ID, även kallat punktläsning
  • Fråga med en filtersats på en enda partitionsnyckel
  • Fråga med en likhets- eller intervallfiltersats på valfri egenskap
  • Fråga utan filter

Frågor som måste köras på alla partitioner har 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öjning har en betydande effekt på frågeprestanda när du behöver göra flera turer eller hämta en stor resultatuppsättning från frågan.

Du kan använda frågekörningsmått för att hämta serverns körningstid för frågor, så att du kan särskilja den tid som ägnas åt frågekörning från tiden under nätverksöverföringen.

Indexeringsprincip

Se Konfigurera indexeringsprincip för indexering av sökvägar, typer och lägen och hur de påverkar frågekörningen. Som standard tillämpar Azure Cosmos DB automatisk indexering på alla data och använder intervallindex för strängar och tal, vilket är effektivt för likhetsfrågor. För scenarier med hög prestanda bör du överväga att undanta sökvägar för att minska RU-kostnaden för varje infogningsåtgärd.

Du kan använda indexmåtten för att identifiera vilka index som används för varje fråga och om det finns några saknade index som skulle förbättra frågeprestandan.

Frågekörningsmått

Detaljerade mått returneras för varje frågekörning i diagnostiken för begäran. De här måtten beskriver var tiden spenderas under frågekörningen och aktiverar avancerad felsökning.

Läs mer om hur du hämtar frågemåtten.

Metric Enhet beskrivning
TotalTime millisekunder Total körningstid för frågor
DocumentLoadTime millisekunder Tidsåtgång vid inläsning av dokument
DocumentWriteTime millisekunder Tidsåtgång för att skriva och serialisera utdatadokumenten
IndexLookupTime millisekunder Tid i fysiskt indexskikt
QueryPreparationTime millisekunder Tid som ägnas åt att förbereda frågan
RuntimeExecutionTime millisekunder Total körningstid för frågekörning
VMExecutionTime millisekunder Tid som ägnas åt att köra frågan i frågekörning
OutputDocumentCount antal Antal utdatadokument i resultatuppsättningen
OutputDocumentSize antal Total storlek på utdatadokument i byte
RetrievedDocumentCount antal Totalt antal hämtade dokument
RetrievedDocumentSize byte Total storlek för hämtade dokument i byte
IndexHitRatio förhållande [0,1] Förhållandet mellan antalet dokument som matchas av filtret och antalet inlästa dokument

Klient-SDK:erna kan internt göra flera frågebegäranden för att hantera frågan inom varje partition. Klienten gör fler än ett anrop per partition om det totala resultatet överskrider alternativet för maximalt antal objekt, om frågan överskrider det etablerade dataflödet för partitionen, om frågenyttolasten når den maximala storleken per sida eller om frågan når den systemallokerade tidsgränsen. Varje partiell frågekörning returnerar frågemått för den sidan.

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

Fråga 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) som spenderas 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 tidigare DocumentLoadTime frågor, men lägre DocumentWriteTime eftersom vi bara projicerar en egenskap.
SELECT TOP 500 udf.toPercent(c.N) FROM c "RuntimeExecutionTime": "00:00:00.2136500" Cirka 213 ms används för RuntimeExecutionTime 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", "RuntimeExecutionTime": "00:00:00.0074100" Cirka 0,6 ms spenderas på IndexLookupTime/Name/?. Merparten av frågekörningstiden (~7 ms) i RuntimeExecutionTime.
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 begäran finns i enheter för begäran.
  • Mer information om indexeringsprincip finns i indexeringsprincip