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
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 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