Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
GÄLLER FÖR:
Mongodb
Important
Vill du migrera ett befintligt MongoDB-program eller använda MQL-funktioner (MongoDB Query Language) ? Överväg Azure DocumentDB.
Letar du efter en databaslösning för storskaliga scenarier med ett serviceavtal på 99,999% tillgänglighetsnivå (SLA), snabb autoskalning och automatisk redundans i flera regioner? Överväg Azure Cosmos DB för NoSQL.
Den här artikeln går igenom en allmän metod som rekommenderas för felsökning av frågor i Azure Cosmos DB. Även om du inte bör betrakta stegen som beskrivs i den här artikeln som ett fullständigt skydd mot potentiella frågeproblem har vi tagit med de vanligaste prestandatipsen här. Du bör använda den här artikeln som utgångspunkt för felsökning av långsamma eller dyra frågor i Azure Cosmos DB:s API för MongoDB. Om du använder Azure Cosmos DB för NoSQL kan du läsa felsökningsguiden för API för NoSQL-frågor.
Frågeoptimeringar i Azure Cosmos DB kategoriseras i stort sett enligt följande:
- Optimeringar som minskar RU-avgiften (Request Unit) för frågan
- Optimeringar som bara minskar svarstiden
Om du minskar RU-avgiften för en fråga minskar du vanligtvis även svarstiden.
Anmärkning
Den här artikeln förutsätter att du använder Azure Cosmos DB:s API för MongoDB-konton med version 3.6 och senare. Vissa frågor som presterar dåligt i version 3.2 har betydande förbättringar i version 3.6+. Uppgradera till version 3.6 genom att lämna in en supportbegäran.
Använd kommandot $explain för att hämta mått
När du optimerar en fråga i Azure Cosmos DB är det första steget alltid att hämta RU-avgiften för din fråga. En riktlinje är att du bör utforska sätt att sänka RU-avgiften för frågor med högre avgift än 50 RU.
Förutom att hämta RU-avgiften bör du använda kommandot $explain för att hämta användningsstatistiken för frågor och index. Här är ett exempel som kör en fråga och använder $explain kommandot för att visa användningsstatistik för frågor och index:
$explain kommando:
db.coll.find({foodGroup: "Baby Foods"}).explain({"executionStatistics": true })
Resultat:
{
"stages" : [
{
"stage" : "$query",
"timeInclusiveMS" : 905.2888,
"timeExclusiveMS" : 905.2888,
"in" : 362,
"out" : 362,
"details" : {
"database" : "db-test",
"collection" : "collection-test",
"query" : {
"foodGroup" : {
"$eq" : "Baby Foods"
}
},
"pathsIndexed" : [],
"pathsNotIndexed" : [
"foodGroup"
],
"shardInformation" : [
{
"activityId" : "e68e6bdd-5e89-4ec5-b053-3dbbc2428140",
"shardKeyRangeId" : "0",
"durationMS" : 788.5867,
"preemptions" : 1,
"outputDocumentCount" : 362,
"retrievedDocumentCount" : 8618
}
],
"queryMetrics" : {
"retrievedDocumentCount" : 8618,
"retrievedDocumentSizeBytes" : 104963042,
"outputDocumentCount" : 362,
"outputDocumentSizeBytes" : 2553535,
"indexHitRatio" : 0.0016802042237178,
"totalQueryExecutionTimeMS" : 777.72,
"queryPreparationTimes" : {
"queryCompilationTimeMS" : 0.19,
"logicalPlanBuildTimeMS" : 0.14,
"physicalPlanBuildTimeMS" : 0.09,
"queryOptimizationTimeMS" : 0.03
},
"indexLookupTimeMS" : 0,
"documentLoadTimeMS" : 687.22,
"vmExecutionTimeMS" : 774.09,
"runtimeExecutionTimes" : {
"queryEngineExecutionTimeMS" : 37.45,
"systemFunctionExecutionTimeMS" : 10.82,
"userDefinedFunctionExecutionTimeMS" : 0
},
"documentWriteTimeMS" : 49.42
}
}
}
],
"estimatedDelayFromRateLimitingInMilliseconds" : 0.0,
"continuation" : {
"hasMore" : false
},
"ok" : 1.0
}
Kommandoutdata $explain är långt och innehåller detaljerad information om frågeexekvering. I allmänhet finns det dock några avsnitt som du bör fokusera på när du optimerar frågeprestanda:
| Mätvärde | Description |
|---|---|
timeInclusiveMS |
Svarstid för backendförfrågan |
pathsIndexed |
Visar index som frågan använde |
pathsNotIndexed |
Visar index som frågan kan ha använt, om det är tillgängligt |
shardInformation |
Sammanfattning av frågeprestanda för en viss fysisk partition |
retrievedDocumentCount |
Antal dokument som läses in av frågemotorn |
outputDocumentCount |
Antal dokument som returneras i frågeresultatet |
estimatedDelayFromRateLimitingInMilliseconds |
Beräknad ytterligare frågesvarstid på grund av hastighetsbegränsning |
När du har hämtat frågemåtten retrievedDocumentCount jämför du med outputDocumentCount för din fråga. Använd den här jämförelsen för att identifiera relevanta avsnitt som ska granskas i den här artikeln.
retrievedDocumentCount är antalet dokument som frågemotorn behöver läsa in.
outputDocumentCount är det antal dokument som behövdes för resultatet av frågan. Om retrievedDocumentCount är betydligt högre än outputDocumentCount kan det finnas minst en del av din sökfråga som inte kunde använda ett index och som behövde utföra en genomsökning.
Se följande avsnitt för att förstå relevanta frågeoptimeringar för ditt scenario.
Sökfrågans RU-avgift är för hög
Antalet hämtade dokument är betydligt högre än antalet utdatadokument
Antal hämtade dokument är ungefär lika med antal utdatadokument
Frågans RU-avgift är acceptabel men svarstiden är fortfarande för hög
Frågor där antalet hämtade dokument överstiger antalet utdatadokument
retrievedDocumentCount är antalet dokument som frågemotorn behövde läsa in.
outputDocumentCount är antalet dokument som returneras av frågan. Om retrievedDocumentCount är betydligt högre än outputDocumentCount kan det finnas minst en del av din sökfråga som inte kunde använda ett index och som behövde utföra en genomsökning.
Här är ett exempel på en genomsökningsfråga som inte helt hanteras av indexet:
$explain kommando:
db.coll.find(
{
$and : [
{ "foodGroup" : "Cereal Grains and Pasta"},
{ "description" : "Oat bran, cooked"}
]
}
).explain({"executionStatistics": true })
Resultat:
{
"stages" : [
{
"stage" : "$query",
"timeInclusiveMS" : 436.5716,
"timeExclusiveMS" : 436.5716,
"in" : 1,
"out" : 1,
"details" : {
"database" : "db-test",
"collection" : "indexing-test",
"query" : {
"$and" : [
{
"foodGroup" : {
"$eq" : "Cereal Grains and Pasta"
}
},
{
"description" : {
"$eq" : "Oat bran, cooked"
}
}
]
},
"pathsIndexed" : [],
"pathsNotIndexed" : [
"foodGroup",
"description"
],
"shardInformation" : [
{
"activityId" : "13a5977e-a10a-4329-b68e-87e4f0081cac",
"shardKeyRangeId" : "0",
"durationMS" : 435.4867,
"preemptions" : 1,
"outputDocumentCount" : 1,
"retrievedDocumentCount" : 8618
}
],
"queryMetrics" : {
"retrievedDocumentCount" : 8618,
"retrievedDocumentSizeBytes" : 104963042,
"outputDocumentCount" : 1,
"outputDocumentSizeBytes" : 6064,
"indexHitRatio" : 0.0,
"totalQueryExecutionTimeMS" : 433.64,
"queryPreparationTimes" : {
"queryCompilationTimeMS" : 0.12,
"logicalPlanBuildTimeMS" : 0.09,
"physicalPlanBuildTimeMS" : 0.1,
"queryOptimizationTimeMS" : 0.02
},
"indexLookupTimeMS" : 0,
"documentLoadTimeMS" : 387.44,
"vmExecutionTimeMS" : 432.93,
"runtimeExecutionTimes" : {
"queryEngineExecutionTimeMS" : 45.36,
"systemFunctionExecutionTimeMS" : 16.86,
"userDefinedFunctionExecutionTimeMS" : 0
},
"documentWriteTimeMS" : 0.13
}
}
}
],
"estimatedDelayFromRateLimitingInMilliseconds" : 0.0,
"continuation" : {
"hasMore" : false
},
"ok" : 1.0
}
( retrievedDocumentCount 8618) är betydligt högre än outputDocumentCount (1), vilket innebär att den här frågan krävde en dokumentgenomsökning.
Inkludera nödvändiga index
Du bör kontrollera matrisen pathsNotIndexed och lägga till dessa index. I det här exemplet ska sökvägarna foodGroup och description indexeras.
"pathsNotIndexed" : [
"foodGroup",
"description"
]
Metodtips för indexering i Azure Cosmos DB:s API för MongoDB skiljer sig från MongoDB. I Azure Cosmos DB:s API för MongoDB används sammansatta index endast i frågor som effektivt behöver sorteras efter flera egenskaper. Om du har frågor med filter för flera egenskaper bör du skapa index för enskilda fält för var och en av dessa egenskaper. Frågepredikat kan använda flera enkla fältindex.
Jokerteckenindex kan förenkla indexeringen. Till skillnad från i MongoDB kan jokerteckenindex stödja flera fält i frågepredikat. Det blir ingen skillnad i frågeprestanda om du använder ett enda jokerteckenindex i stället för att skapa ett separat index för varje egenskap. Att lägga till ett jokerteckenindex för alla egenskaper är det enklaste sättet att optimera alla dina frågor.
Du kan lägga till nya index när som helst, utan att det påverkar skriv- eller lästillgängligheten. Du kan spåra indextransformeringens förlopp.
Förstå vilka aggregeringsåtgärder som använder indexet
I de flesta fall använder aggregeringsåtgärder i Azure Cosmos DB:s API för MongoDB delvis index. Vanligtvis tillämpar frågemotorn likhets- och intervallfilter först och använder index. När dessa filter har tillämpats kan frågemotorn utvärdera ytterligare filter och vid behov ta till läsning av återstående dokument för att beräkna aggregatet.
Här är ett exempel:
db.coll.aggregate( [
{ $match: { foodGroup: 'Fruits and Fruit Juices' } },
{
$group: {
_id: "$foodGroup",
total: { $max: "$version" }
}
}
] )
I det här fallet kan index optimera $match fasen. Om du lägger till ett index för foodGroup förbättras frågeprestanda avsevärt. Precis som i MongoDB bör du placera $match så tidigt i aggregeringspipelinen som möjligt för att maximera användningen av index.
I Azure Cosmos DB:s API för MongoDB används inte index för den faktiska aggregeringen, som i det här fallet är $max. Om du lägger till ett index på version förbättras inte frågeprestandan.
Frågor där det hämtade antalet dokument är lika med antal utdatadokument
retrievedDocumentCount Om är ungefär lika med outputDocumentCountbehövde frågemotorn inte skanna många onödiga dokument.
Minimera förfrågningar mellan partitioner
Azure Cosmos DB använder partitionering för att skala enskilda containrar när begärandeenheten och datalagringsbehoven ökar. Varje fysisk partition har ett separat och oberoende index. Om frågan har ett likhetsfilter som matchar containerns partitionsnyckel behöver du bara kontrollera den relevanta partitionens index. Den här optimeringen minskar det totala antalet RU:er som frågan kräver. Läs mer om skillnaderna mellan partitionsfrågor och frågor mellan partitioner.
Om du har ett stort antal etablerade RU:er (mer än 30 000) eller en stor mängd data lagrade (mer än cirka 100 GB), har du förmodligen en tillräckligt stor container för att märka en betydande minskning av fråge-RU-avgifterna.
Du kan kontrollera matrisen shardInformation för att förstå frågemåtten för varje enskild fysisk partition. Antalet unika shardKeyRangeId värden är antalet fysiska partitioner där frågan behövde köras. I det här exemplet kördes frågan på fyra fysiska partitioner. Det är viktigt att förstå att exekvering är helt oberoende av användning av index. Med andra ord kan frågor mellan partitioner fortfarande använda index.
"shardInformation" : [
{
"activityId" : "42f670a8-a201-4c58-8023-363ac18d9e18",
"shardKeyRangeId" : "5",
"durationMS" : 24.3859,
"preemptions" : 1,
"outputDocumentCount" : 463,
"retrievedDocumentCount" : 463
},
{
"activityId" : "a8bf762a-37b9-4c07-8ed4-ae49961373c0",
"shardKeyRangeId" : "2",
"durationMS" : 35.8328,
"preemptions" : 1,
"outputDocumentCount" : 905,
"retrievedDocumentCount" : 905
},
{
"activityId" : "3754e36b-4258-49a6-8d4d-010555628395",
"shardKeyRangeId" : "1",
"durationMS" : 67.3969,
"preemptions" : 1,
"outputDocumentCount" : 1479,
"retrievedDocumentCount" : 1479
},
{
"activityId" : "a69a44ee-db97-4fe9-b489-3791f3d52878",
"shardKeyRangeId" : "0",
"durationMS" : 185.1523,
"preemptions" : 1,
"outputDocumentCount" : 867,
"retrievedDocumentCount" : 867
}
]
Optimeringar som minskar frågefördröjningen
I många fall kan RU-avgiften vara acceptabel även om svarstiden för frågor är för lång. I följande avsnitt finns en översikt med tips om hur svarstiden för frågor kan minskas. Om du kör samma fråga flera gånger på samma datamängd får den vanligtvis samma RU-avgift varje gång. Frågesvarstiden kan dock variera mellan frågekörningar.
Förbättra närhet
Frågor som körs från en annan region än Azure Cosmos DB-kontot har högre svarstid än om de kördes i samma region. Om du till exempel kör kod på din stationära dator bör du förvänta dig att svarstiden blir tiotals eller hundratals millisekunder längre (eller mer) än om frågan kom från en virtuell dator i samma Azure-region som Azure Cosmos DB. Det är enkelt att distribuera data globalt i Azure Cosmos DB för att säkerställa att du kan föra dina data närmare din app.
Öka tilldelad genomströmning
I Azure Cosmos DB mäts din tilldelade datagenomströmning i förfrågningsenheter (RU:er). Anta att du har en fråga som förbrukar 5 RU av dataflödet. Om du till exempel etablerar 1 000 RU skulle du kunna köra frågan 200 gånger per sekund. Om du försökte köra frågan när det inte fanns tillräckligt med dataflöde tillgängligt begränsar Azure Cosmos DB antalet begäranden. Azure Cosmos DB:s API för MongoDB gör automatiskt ett nytt försök efter en kort stund. Strypta förfrågningar tar längre tid, så att öka det allokerade dataflödet kan förbättra förfrågans svarstid.
Värdet estimatedDelayFromRateLimitingInMilliseconds ger en uppfattning om de potentiella svarstidsfördelarna om du ökar dataflödet.
Nästa steg
- Felsöka frågeprestanda (API för NoSQL)
- Förhindra hastighetsbegränsning med SSR
- Hantera indexering i Azure Cosmos DB-API för MongoDB
- Försöker du planera kapacitet för en migrering till Azure Cosmos DB? Du kan använda information om ditt befintliga databaskluster för kapacitetsplanering.
- Om allt du vet är antalet virtuella kärnor och servrar i ditt befintliga databaskluster bör du läsa om hur man uppskattar förfrågningsenheter med virtuella kärnor eller vCPU:er
- Om du känner till vanliga begärandefrekvenser för din aktuella databasarbetsbelastning kan du läsa om beräkning av enheter för begäranden med hjälp av Azure Cosmos DB kapacitetsplanerare