Ladění výkonu dotazů pomocí služby Azure Cosmos DB
PLATÍ PRO:
SQL API
Azure Cosmos DB poskytuje rozhraní API SQL prodotazování dat bez vyžadování schématu nebo sekundárních indexů. Tento článek obsahuje následující informace pro vývojáře:
- Podrobné informace o tom, jak Cosmos dotazování služby Azure SQL DB funguje
- Podrobnosti o hlavičkách požadavku a odpovědi dotazu a možnostech klientské sady SDK
- Tipy a osvědčené postupy pro výkon dotazů
- Příklady využití statistik spouštění SQL k ladění výkonu dotazů
Informace SQL dotazu
Ve službě Azure Cosmos DB ukládáte data do kontejnerů, které se mohou zvětšovat na libovolnou velikost úložiště nebo propustnost požadavků. Azure Cosmos DB bezproblémově škáluje data napříč fyzickými oddíly na pokrývce, aby zvládla nárůst nebo zvýšení zřízené propustnosti. Dotazy na SQL kontejneru můžete vydávat pomocí REST API nebo jedné z podporovaných SQL SDK.
Stručný přehled dělení: Definujete klíč oddílu, jako je "město", který určuje, jak se data rozdělí mezi fyzické oddíly. Data patřící do jednoho klíče oddílu (například "city" == "Seattle") se ukládají v rámci fyzického oddílu, ale obvykle má jeden fyzický oddíl více klíčů oddílu. Když oddíl dosáhne velikosti úložiště, služba ho bezproblémově rozdělí na dva nové oddíly a rozdělí klíč oddílu rovnoměrně mezi tyto oddíly. Vzhledem k tomu, že oddíly jsou přechodné, rozhraní API používají abstrakci "rozsahu klíčů oddílů", která označuje rozsahy hodnot hash klíčů oddílů.
Když vydáte dotaz do služby Azure Cosmos DB, sada SDK provede tyto logické kroky:
- Parsujte SQL dotazu a určete plán spuštění dotazu.
- Pokud dotaz obsahuje filtr podle klíče oddílu, jako je
SELECT * FROM c WHERE c.city = "Seattle", je směrován do jednoho oddílu. Pokud dotaz nemá filtr na klíč oddílu, provede se ve všech oddílech a výsledky se sloučí na straně klienta. - Dotaz se provádí v rámci každého oddílu v řadě nebo paralelně na základě konfigurace klienta. V rámci každého oddílu může dotaz provést jednu nebo více cest round trips v závislosti na složitosti dotazu, nakonfigurované velikosti stránky a zřízené propustnosti kolekce. Každé spuštění vrátí počet jednotek žádostí spotřebovaných prováděním dotazu a volitelně statistiky provádění dotazů.
- Sada SDK provede souhrn výsledků dotazu napříč oddíly. Pokud například dotaz zahrnuje ORDER BY napříč oddíly, výsledky z jednotlivých oddílů se seřadí sloučením, aby se výsledky vrátily v globálně seřazeném pořadí. Pokud je dotaz agregace, jako je , počty z jednotlivých oddílů se sečtou, aby
COUNTse získal celkový počet.
Tyto sdk poskytují různé možnosti spouštění dotazů. Například v rozhraní .NET jsou tyto možnosti k dispozici ve FeedOptions třídě . Následující tabulka popisuje tyto možnosti a jejich vliv na dobu provádění dotazů.
| Možnost | Popis |
|---|---|
EnableCrossPartitionQuery |
Pro všechny dotazy, které vyžadují spuštění napříč více než jedním oddílem, musí být nastavená hodnota true. Toto je explicitní příznak, který vám umožní při vývoji dělat vědomé kompromisy z výkonu. |
EnableScanInQuery |
Pokud jste se odhlásit z indexování, ale přesto chcete spustit dotaz prostřednictvím kontroly, musí být nastavená na hodnotu true. Platí pouze v případě, že je indexování požadované cesty filtru zakázané. |
MaxItemCount |
Maximální počet položek, které se vrátí za zpáteční cestu na server. Nastavením na -1 můžete nechat server spravovat počet položek. Nebo můžete tuto hodnotu snížit, aby se načítá pouze malý počet položek za zpáteční cestu. |
MaxBufferedItemCount |
Jedná se o možnost na straně klienta, která slouží k omezení spotřeby paměti při provádění příkazu ORDER BY mezi oddíly. Vyšší hodnota pomáhá snížit latenci řazení napříč oddíly. |
MaxDegreeOfParallelism |
Získá nebo nastaví počet souběžných operací spuštěných na straně klienta během paralelního spouštění dotazů ve službě Azure Cosmos database service. Kladná hodnota vlastnosti omezuje počet souběžných operací na nastavenou hodnotu. Pokud je nastavená menší než 0, systém automaticky rozhodne o počtu souběžných operací, které se budou spouštět. |
PopulateQueryMetrics |
Umožňuje podrobné protokolování statistiky času stráveného v různých fázích provádění dotazů, jako je doba kompilace, doba smyčky indexu a doba načítání dokumentu. Výstup ze statistik dotazů můžete sdílet s Podpora Azure a diagnostikovat problémy s výkonem dotazů. |
RequestContinuation |
Provádění dotazů můžete obnovit předáním neprůhledného tokenu pokračování vráceného libovolným dotazem. Pokračovací token zapouzdřuje všechny stavy potřebné ke spuštění dotazu. |
ResponseContinuationTokenLimitInKb |
Můžete omezit maximální velikost pokračovacího tokenu vráceného serverem. Tuto možnost možná budete muset nastavit, pokud má hostitel aplikace omezení velikosti hlavičky odpovědi. Nastavením této možnosti se může zvýšit celková doba trvání a počet SPOTŘEBOVANÝCH PRO dotaz. |
Podívejme se například na příklad dotazu na klíč oddílu požadovaný pro kolekci s klíčem oddílu a /city zřízením propustnosti 100 000 RU/s. Tento dotaz si vyžádáte CreateDocumentQuery<T> v .NET následujícím způsobem:
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();
Výše uvedený fragment kódu sady SDK odpovídá následujícímu REST API požadavku:
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'"}
Každá stránka spuštění dotazu odpovídá REST API s hlavičkou a SQL POST Accept: application/query+json dotazu v těle. Každý dotaz provede jednu nebo více cest k serveru s tokenem, který se vyklenuje mezi klientem a serverem a x-ms-continuation pokračuje v provádění. Možnosti konfigurace v FeedOptions se předá serveru ve formě hlaviček požadavku. Například odpovídá MaxItemCount . x-ms-max-item-count
Požadavek vrátí následující odpověď (zkrácenou kvůli čitelnosti):
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
Mezi hlavičky klíčových odpovědí vrácené dotazem patří:
| Možnost | Popis |
|---|---|
x-ms-item-count |
Počet položek vrácených v odpovědi To závisí na zadaném parametru , počtu položek, které se vejdou do maximální velikosti datové části odpovědi, zřízené propustnosti a x-ms-max-item-count doby provádění dotazu. |
x-ms-continuation: |
Token pro pokračování, který obnoví provádění dotazu, pokud jsou k dispozici další výsledky. |
x-ms-documentdb-query-metrics |
Statistika dotazu pro spuštění. Jedná se o řetězec s oddělovači obsahující statistiku času stráveného v různých fázích provádění dotazu. Vrátí x-ms-documentdb-populatequerymetrics se, pokud je nastavená hodnota True . |
x-ms-request-charge |
Počet jednotek žádostí spotřebovaných dotazem |
Podrobnosti o hlavičkách a REST API požadavku najdete v tématu Dotazování prostředků pomocí REST API.
Osvědčené postupy pro výkon dotazů
Níže jsou uvedené nejběžnější faktory, které ovlivňují výkon dotazů Azure Cosmos DB. Každé z těchto témat v tomto článku se budeme ponořit hlouběji.
| Faktor | Tip |
|---|---|
| Zřízená propustnost | Změřte RU na dotaz a ujistěte se, že máte požadovanou zřízenou propustnost pro vaše dotazy. |
| Dělení a klíče oddílů | Kvůli nízké latenci upřednostňujte dotazy s hodnotou klíče oddílu v klauzuli filter. |
| Možnosti sady SDK a dotazů | Dodržujte osvědčené postupy sady SDK, jako je přímé připojení, a vylaďte možnosti spouštění dotazů na straně klienta. |
| Zásady indexování | Ujistěte se, že pro dotaz máte požadované cesty nebo zásady indexování. |
| Metriky spouštění dotazů | Analyzujte metriky spouštění dotazů a identifikujte potenciální přepsání tvarů dotazů a dat. |
Zřízená propustnost
V Cosmos DB vytvoříte kontejnery dat, z nichž každý má rezervovanou propustnost vyjádřenou v jednotkách žádostí (RU) za sekundu. Čtení 1kB dokumentu je 1 RU a každá operace (včetně dotazů) se normalizuje na pevný počet RU na základě jeho složitosti. Pokud máte například pro kontejner zřízeno 1 000 RU/s a máte dotaz typu , který spotřebovává 5 RU, můžete takové dotazy SELECT * FROM c WHERE c.city = 'Seattle' provést (1 000 RU/s) / (5 RU/dotaz) = 200 dotazů za sekundu.
Pokud odešlete více než 200 dotazů za sekundu, služba začne omezovat rychlost příchozích požadavků nad 200/s. Sdk tento případ automaticky zvládá provedením opakování/opakování, takže si můžete všimnout vyšší latence pro tyto dotazy. Zvýšením zřízené propustnosti na požadovanou hodnotu se zvýší latence a propustnost dotazů.
Další informace o jednotkách žádostí najdete v tématu Jednotky žádostí.
Dělení a klíče oddílů
Při použití azure Cosmos DB se dotazy obvykle provádějí v následujícím pořadí od nejrychlejšího, nejúčinnějšího až po pomalejší a méně efektivní.
- GET pro jeden klíč oddílu a klíč položky
- Dotaz s klauzulí filtru na jeden klíč oddílu
- Dotazování bez klauzule filtru rovnosti nebo rozsahu pro libovolnou vlastnost
- Dotazování bez filtrů
Dotazy, které potřebují prostudovat všechny oddíly, potřebují vyšší latenci a mohou spotřebovávat vyšší počet DOTAZŮ. Vzhledem k tomu, že každý oddíl má automatické indexování proti všem vlastnostem, lze dotaz v tomto případě efektivně zpracovat z indexu. Pomocí možností paralelismus můžete vytvářet dotazy, které přesahují oddíly rychleji.
další informace o dělení a klíčích oddílů najdete v tématu dělení v Azure Cosmos DB.
Sada SDK a možnosti dotazu
informace o tom, jak dosáhnout nejlepšího výkonu na straně klienta z Azure Cosmos DB, najdete v tématu Tipy výkonu a testování výkonu . To zahrnuje použití nejnovějších sad SDK, konfigurace konfigurací specifických pro konkrétní platformu, jako je výchozí počet připojení, frekvence uvolňování paměti a použití zjednodušených možností připojení, jako je Direct/TCP.
Maximální počet položek
V případě dotazů MaxItemCount může mít hodnota významného vlivu na koncové časy dotazů. Při každé operaci odezvy na server nebude vráceno více než počet položek MaxItemCount (výchozí hodnota je 100 položek). Nastavení této hodnoty na vyšší hodnotu (-1 je maximum a doporučeno) vylepší celkovou dobu trvání dotazu tím, že omezí počet přenosů mezi serverem a klientem, zejména pro dotazy s velkými sadami výsledků.
IDocumentQuery<dynamic> query = client.CreateDocumentQuery(
UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName),
"SELECT * FROM c WHERE c.city = 'Seattle'",
new FeedOptions
{
MaxItemCount = -1,
}).AsDocumentQuery();
Maximální stupeň paralelismu
V případě dotazů můžete vyladit MaxDegreeOfParallelism a identifikovat nejlepší konfigurace pro vaši aplikaci, zejména pokud provádíte dotazy mezi oddíly (bez filtru na hodnotu klíče oddílu). MaxDegreeOfParallelism Určuje maximální počet paralelních úloh, tj. maximální počet oddílů, které mají být navštíveny paralelně.
IDocumentQuery<dynamic> query = client.CreateDocumentQuery(
UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName),
"SELECT * FROM c WHERE c.city = 'Seattle'",
new FeedOptions
{
MaxDegreeOfParallelism = -1,
EnableCrossPartitionQuery = true
}).AsDocumentQuery();
Pojďme předpokládat, že
- D = výchozí maximální počet paralelních úloh (= celkový počet procesorů v klientském počítači)
- P = uživatelem zadaný maximální počet paralelních úkolů
- N = počet oddílů, které musí být navštíveny pro zodpovězení dotazu
Níže jsou uvedené důsledky, jak se paralelní dotazy budou chovat pro různé hodnoty P.
- (P = = 0) => sériového režimu
- (P = = 1) => maximálně jeden úkol
- (P > 1) => min (P, N) Paralelní úlohy
- (P < 1) => min (N, D) Paralelní úlohy
poznámky k verzi sady SDK a podrobnosti o implementovaných třídách a metodách naleznete v tématu SQL sdk .
Latence sítě
jak nastavit globální distribuci a připojit se k nejbližší oblasti, najdete v tématu Azure Cosmos DB globální distribuce . Latence sítě má významný dopad na výkon dotazů, pokud potřebujete udělat více přenosových cest nebo načíst velkou sadu výsledků dotazu.
Oddíl metriky spouštění dotazů vysvětluje, jak načíst dobu provádění dotazů ( totalExecutionTimeInMs ), takže můžete rozlišovat čas strávený při provádění dotazů a čas strávený při přenosu v síti.
Zásada indexování
Viz téma Konfigurace zásad indexování pro cesty, druhy a režimy indexování a to, jak ovlivňují provádění dotazů. Ve výchozím nastavení zásada indexování používá indexování rozsahu pro řetězce, které jsou platné pro dotazy na rovnost. Pokud pro řetězce potřebujete dotazy na rozsah, doporučujeme zadat typ indexu rozsahu pro všechny řetězce.
ve výchozím nastavení Azure Cosmos DB použije automatické indexování na všechna data. V případě scénářů vkládání s vysokým výkonem zvažte možnost vyloučení cest, protože se tím sníží náklady na RU za každou operaci vložení.
Metriky spuštění dotazu
Podrobné metriky pro provádění dotazů můžete získat předáním volitelné x-ms-documentdb-populatequerymetrics hlavičky ( FeedOptions.PopulateQueryMetrics v sadě .NET SDK). Hodnota vrácená v x-ms-documentdb-query-metrics má následující páry klíč-hodnota, které jsou určeny pro pokročilé řešení potíží s prováděním dotazů.
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 | Jednotka | Description |
|---|---|---|
totalExecutionTimeInMs |
milisekundy | Čas provedení dotazu |
queryCompileTimeInMs |
milisekundy | Čas kompilace dotazu |
queryLogicalPlanBuildTimeInMs |
milisekundy | Čas k sestavení plánu logického dotazu |
queryPhysicalPlanBuildTimeInMs |
milisekundy | Čas k sestavení fyzického plánu dotazu |
queryOptimizationTimeInMs |
milisekundy | Čas strávený v optimalizaci dotazu |
VMExecutionTimeInMs |
milisekundy | Čas strávený v modulu runtime dotazů |
indexLookupTimeInMs |
milisekundy | Čas strávený fyzickou indexovou vrstvou |
documentLoadTimeInMs |
milisekundy | Čas strávený načítáním dokumentů |
systemFunctionExecuteTimeInMs |
milisekundy | Celkový čas strávený prováděním systému (integrovaných) funkcí v milisekundách |
userFunctionExecuteTimeInMs |
milisekundy | Celkový čas strávený prováděním uživatelsky definovaných funkcí v milisekundách |
retrievedDocumentCount |
count | Celkový počet načtených dokumentů |
retrievedDocumentSize |
psaný | Celková velikost načtených dokumentů v bajtech |
outputDocumentCount |
count | Počet výstupních dokumentů |
writeOutputTimeInMs |
milisekundy | Čas strávený zápisem výstupu v milisekundách |
indexUtilizationRatio |
poměr (<= 1) | Poměr počtu dokumentů odpovídajících filtru na počet načtených dokumentů |
Klientské sady SDK mohou interně provádět dotazy v rámci jednotlivých oddílů. Klient provede více než jedno volání na oddíl, pokud celkový výsledek překročí x-ms-max-item-count , pokud dotaz překračuje zřízenou propustnost pro oddíl, nebo pokud datová část dotazu dosáhne maximální velikosti na stránce nebo pokud dotaz dosáhne časového limitu přiděleného systému. Každé částečné spuštění dotazu vrátí x-ms-documentdb-query-metrics pro tuto stránku.
Tady je několik ukázkových dotazů a postup interpretace některých metrik vrácených spuštěním dotazu:
| Dotaz | Ukázková metrika | Description |
|---|---|---|
SELECT TOP 100 * FROM c |
"RetrievedDocumentCount": 101 |
Počet načtených dokumentů je 100 + 1, aby se shodovala s horní klauzulí. Čas dotazu se většinou stráví v WriteOutputTime a DocumentLoadTime vzhledem k tomu, že se jedná o kontrolu. |
SELECT TOP 500 * FROM c |
"RetrievedDocumentCount": 501 |
RetrievedDocumentCount je teď vyšší (500 + 1 tak, aby odpovídalo horní klauzuli). |
SELECT * FROM c WHERE c.N = 55 |
"IndexLookupTime": "00:00:00.0009500" |
Přibližně 0,9 MS vychází z IndexLookupTime pro vyhledávání klíčů, protože se jedná o vyhledávání v indexu /N/? . |
SELECT * FROM c WHERE c.N > 55 |
"IndexLookupTime": "00:00:00.0017700" |
Ještě více času (1,7 MS) strávených IndexLookupTime nad kontrolou rozsahu, protože se jedná o vyhledávání v indexu /N/? . |
SELECT TOP 500 c.N FROM c |
"IndexLookupTime": "00:00:00.0017700" |
Stejný čas strávený na DocumentLoadTime předchozích dotazech, ale nižší, WriteOutputTime protože probíhá projekce pouze jedné vlastnosti. |
SELECT TOP 500 udf.toPercent(c.N) FROM c |
"UserDefinedFunctionExecutionTime": "00:00:00.2136500" |
Přibližně 213 MS se stráví UserDefinedFunctionExecutionTime spouštěním systému souborů UDF na každé hodnotě c.N . |
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(c.Name, 'Den') |
"IndexLookupTime": "00:00:00.0006400", "SystemFunctionExecutionTime": "00:00:00.0074100" |
Přibližně v systému je vyčerpáno 0,6 MS IndexLookupTime /Name/? . Většina času provedení dotazu (~ 7 MS) v SystemFunctionExecutionTime . |
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(LOWER(c.Name), 'den') |
"IndexLookupTime": "00:00:00", "RetrievedDocumentCount": 2491, "OutputDocumentCount": 500 |
Dotaz je proveden jako kontrola, protože používá LOWER a je vráceno 500 z 2491 načtených dokumentů. |
Další kroky
- další informace o podporovaných operátorech a klíčových slovech SQL dotazů naleznete v tématu SQL query.
- Další informace o jednotkách žádostí najdete v tématu jednotky žádostí.
- Další informace o zásadách indexování najdete v tématu indexování zásad .