Tuning query performance with Azure Cosmos DB (Dostosowywanie wydajności zapytań w usłudze Azure Cosmos DB)
DOTYCZY: NoSQL
Usługa Azure Cosmos DB udostępnia interfejs API dla noSQL do wykonywania zapytań dotyczących danych bez konieczności tworzenia schematów ani indeksów pomocniczych. Ten artykuł zawiera następujące informacje dla deweloperów:
- Ogólne informacje na temat działania wykonywania zapytań SQL w usłudze Azure Cosmos DB
- Porady i najlepsze rozwiązania dotyczące wydajności zapytań
- Przykłady korzystania z metryk wykonywania zapytań SQL w celu debugowania wydajności zapytań
Informacje o wykonywaniu zapytań SQL
W usłudze Azure Cosmos DB dane są przechowywane w kontenerach, co może zwiększać się do dowolnego rozmiaru magazynu lub żądać przepływności. Usługa Azure Cosmos DB bezproblemowo skaluje dane między partycjami fizycznymi w ramach okładek w celu obsługi wzrostu danych lub zwiększenia aprowizowanej przepływności. Zapytania SQL można wysyłać do dowolnego kontenera przy użyciu interfejsu API REST lub jednego z obsługiwanych zestawów SDK SQL.
Krótkie omówienie partycjonowania: definiujesz klucz partycji, taki jak "miasto", który określa sposób dzielenia danych między partycje fizyczne. Dane należące do pojedynczego klucza partycji (na przykład "miasto" == "Seattle") są przechowywane w partycji fizycznej, a pojedyncza partycja fizyczna może przechowywać dane z wielu kluczy partycji. Gdy partycja osiągnie limit magazynu, usługa bezproblemowo dzieli partycję na dwie nowe partycje. Dane są dystrybuowane równomiernie w nowych partycjach, zachowując wszystkie dane dla pojedynczego klucza partycji. Ponieważ partycje są przejściowe, interfejsy API używają abstrakcji zakresu kluczy partycji, który określa zakresy skrótów kluczy partycji.
W przypadku wysyłania zapytania do usługi Azure Cosmos DB zestaw SDK wykonuje następujące kroki logiczne:
- Przeanalizuj zapytanie SQL, aby określić plan wykonywania zapytania.
- Jeśli zapytanie zawiera filtr względem klucza partycji, na przykład
SELECT * FROM c WHERE c.city = "Seattle"
, jest kierowany do pojedynczej partycji. Jeśli zapytanie nie ma filtru na kluczu partycji, jest wykonywane we wszystkich partycjach i wyniki z każdej partycji są scalane po stronie klienta. - Zapytanie jest wykonywane w ramach każdej partycji w serii lub równolegle na podstawie konfiguracji klienta. W ramach każdej partycji zapytanie może wykonywać co najmniej jedną rundę w zależności od złożoności zapytania, skonfigurowanego rozmiaru strony i aprowizowanej przepływności kolekcji. Każde wykonanie zwraca liczbę jednostek żądań używanych przez wykonywanie zapytań i statystyki wykonywania zapytań.
- Zestaw SDK wykonuje podsumowanie wyników zapytania między partycjami. Jeśli na przykład zapytanie obejmuje element ORDER BY między partycjami, wyniki z poszczególnych partycji są sortowane w celu zwrócenia wyników w kolejności posortowanej globalnie. Jeśli zapytanie jest agregacją, na przykład
COUNT
, liczby z poszczególnych partycji są sumowane w celu utworzenia ogólnej liczby.
Zestawy SDK udostępniają różne opcje wykonywania zapytań. Na przykład na platformie .NET te opcje są dostępne w QueryRequestOptions
klasie . W poniższej tabeli opisano te opcje i sposób ich wpływu na czas wykonywania zapytania.
Opcja | Opis |
---|---|
EnableScanInQuery |
Ma zastosowanie tylko wtedy, gdy indeksowanie żądanej ścieżki filtru jest wyłączone. Należy ustawić wartość true, jeśli zrezygnowano z indeksowania i chcesz uruchamiać zapytania przy użyciu pełnego skanowania. |
MaxItemCount |
Maksymalna liczba elementów do zwrócenia na serwer w obie strony. Można ustawić wartość -1, aby umożliwić serwerowi zarządzanie liczbą elementów do zwrócenia. |
MaxBufferedItemCount |
Maksymalna liczba elementów, które mogą być buforowane po stronie klienta podczas równoległego wykonywania zapytań. Dodatnia wartość właściwości ogranicza liczbę buforowanych elementów do ustawionej wartości. Można ustawić wartość mniejszą niż 0, aby system automatycznie decydował o liczbie elementów do buforowania. |
MaxConcurrency |
Pobiera lub ustawia liczbę równoczesnych operacji uruchamianych po stronie klienta podczas równoległego wykonywania zapytań. Wartość właściwości dodatniej ogranicza liczbę operacji współbieżnych do ustawionej wartości. Można ustawić wartość mniejszą niż 0, aby umożliwić systemowi automatyczne decydowanie o liczbie równoczesnych operacji do uruchomienia. |
PopulateIndexMetrics |
Umożliwia zbieranie metryk indeksu, aby zrozumieć, jak aparat zapytań używał istniejących indeksów i jak może korzystać z potencjalnych nowych indeksów. Ta opcja powoduje narzut, dlatego należy ją włączyć tylko podczas debugowania wolnych zapytań. |
ResponseContinuationTokenLimitInKb |
Maksymalny rozmiar tokenu kontynuacji zwracanego przez serwer można ograniczyć. Może być konieczne ustawienie tego ustawienia, jeśli host aplikacji ma limity rozmiaru nagłówka odpowiedzi, ale może zwiększyć całkowity czas trwania i jednostki RU używane dla zapytania. |
Na przykład poniżej przedstawiono zapytanie dotyczące kontenera podzielonego na partycje przy użyciu /city
zestawu SDK platformy .NET:
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();
Każde wykonanie zapytania odpowiada interfejsowi API POST
REST z nagłówkami ustawionymi dla opcji żądania zapytania i zapytania SQL w treści. Aby uzyskać szczegółowe informacje na temat nagłówków i opcji żądań interfejsu API REST, zobacz Wykonywanie zapytań dotyczących zasobów przy użyciu interfejsu API REST.
Najlepsze rozwiązania dotyczące wydajności zapytań
Następujące czynniki często mają największy wpływ na wydajność zapytań usługi Azure Cosmos DB. Bardziej szczegółowo omówimy każdy z tych czynników w tym artykule.
Współczynnik | Napiwek |
---|---|
Aprowizowana przepływność | Zmierz jednostkę RU na zapytanie i upewnij się, że masz wymaganą aprowizowaną przepływność dla zapytań. |
Partycjonowanie i klucze partycji | Faworyzowanie zapytań przy użyciu wartości klucza partycji w klauzuli filtru w celu uzyskania małych opóźnień. |
Zestaw SDK i opcje zapytań | Postępuj zgodnie z najlepszymi rozwiązaniami dotyczącymi zestawu SDK, takimi jak łączność bezpośrednia, i dostosuj opcje wykonywania zapytań po stronie klienta. |
Opóźnienie sieci | Uruchom aplikację w tym samym regionie co konto usługi Azure Cosmos DB wszędzie tam, gdzie jest to możliwe, aby zmniejszyć opóźnienie. |
Zasady indeksowania | Upewnij się, że masz wymagane ścieżki indeksowania/zasady dla zapytania. |
Metryki wykonywania zapytań | Przeanalizuj metryki wykonywania zapytania, aby zidentyfikować potencjalne ponowne zapisywanie kształtów zapytań i danych. |
Aprowizowana przepływność
W usłudze Azure Cosmos DB tworzysz kontenery danych, z których każda ma zarezerwowaną przepływność wyrażoną w jednostkach żądań (RU) na sekundę. Odczyt dokumentu o rozmiarze 1 KB to jedna jednostka RU, a każda operacja (w tym zapytania) jest znormalizowana do stałej liczby jednostek RU na podstawie jego złożoności. Jeśli na przykład masz aprowizowaną liczbę 1000 RU/s dla kontenera i masz zapytanie podobne SELECT * FROM c WHERE c.city = 'Seattle'
do tego, które zużywa 5 jednostek RU, możesz wykonać (1000 RU/s) / (5 RU/zapytanie) = 200 z tych zapytań na sekundę.
Jeśli przesyłasz więcej niż 200 zapytań na sekundę (lub inne operacje, które saturacji wszystkich aprowizowania jednostek RU), usługa uruchamia żądania przychodzące ograniczające szybkość. Zestawy SDK automatycznie obsługują ograniczanie szybkości, wykonując wycofywanie/ponawianie próby, dlatego może zauważyć większe opóźnienie dla tych zapytań. Zwiększenie aprowizowanej przepływności do wymaganej wartości zwiększa opóźnienie zapytań i przepływność.
Aby dowiedzieć się więcej o jednostkach żądań, zobacz Jednostki żądań.
Partycjonowanie i klucze partycji
W przypadku usługi Azure Cosmos DB następujące scenariusze odczytu danych są uporządkowane według tego, co jest zwykle najszybsze/najbardziej wydajne do najwolniejszych/najmniej wydajnych.
- GET dla pojedynczego klucza partycji i identyfikatora elementu, znanego również jako odczyt punktu
- Wykonywanie zapytań przy użyciu klauzuli filtru dla pojedynczego klucza partycji
- Wykonywanie zapytań z klauzulą filtrowania równości lub zakresu dla dowolnej właściwości
- Wykonywanie zapytań bez filtrów
Zapytania, które należy wykonać na wszystkich partycjach, mają większe opóźnienie i mogą zużywać wyższe jednostki RU. Ponieważ każda partycja ma automatyczne indeksowanie we wszystkich właściwościach, zapytanie może być obsługiwane wydajnie z indeksu w tym przypadku. Zapytania obejmujące partycje można szybciej tworzyć przy użyciu opcji równoległości.
Aby dowiedzieć się więcej na temat partycjonowania i kluczy partycji, zobacz Partycjonowanie w usłudze Azure Cosmos DB.
Zestaw SDK i opcje zapytań
Zobacz porady dotyczące wydajności zapytań i testowanie wydajności, aby dowiedzieć się, jak uzyskać najlepszą wydajność po stronie klienta z usługi Azure Cosmos DB przy użyciu naszych zestawów SDK.
Opóźnienie sieci
Zobacz globalną dystrybucję usługi Azure Cosmos DB, aby dowiedzieć się, jak skonfigurować dystrybucję globalną i połączyć się z najbliższym regionem. Opóźnienie sieci ma znaczący wpływ na wydajność zapytań, gdy trzeba wykonać wiele rund lub pobrać duży zestaw wyników z zapytania.
Możesz użyć metryk wykonywania zapytań, aby pobrać czas wykonywania serwera zapytań, co umożliwia odróżnienie czasu spędzonego w wykonywaniu zapytań od czasu spędzonego w trakcie przesyłania sieciowego.
Zasady indeksowania
Zobacz konfigurowanie zasad indeksowania dla ścieżek indeksowania, rodzajów i trybów oraz sposobu ich wpływu na wykonywanie zapytań. Domyślnie usługa Azure Cosmos DB stosuje automatyczne indeksowanie do wszystkich danych i używa indeksów zakresu dla ciągów i liczb, co jest skuteczne w przypadku zapytań równości. W przypadku scenariuszy wstawiania o wysokiej wydajności rozważ wykluczenie ścieżek, aby zmniejszyć koszt jednostek ŻĄDANIA dla każdej operacji wstawiania.
Możesz użyć metryk indeksu, aby określić, które indeksy są używane dla każdego zapytania, i jeśli brakuje indeksów, które poprawiłyby wydajność zapytań.
Metryki wykonywania zapytań
Szczegółowe metryki są zwracane dla każdego wykonania zapytania w diagnostyce żądania. Te metryki opisują czas spędzony podczas wykonywania zapytania i umożliwiają zaawansowane rozwiązywanie problemów.
Dowiedz się więcej na temat pobierania metryk zapytań.
Metric | Jednostka | opis |
---|---|---|
TotalTime |
milisekundy | Łączny czas wykonywania zapytania |
DocumentLoadTime |
milisekundy | Czas spędzony na ładowaniu dokumentów |
DocumentWriteTime |
milisekundy | Czas poświęcony na pisanie i serializowanie dokumentów wyjściowych |
IndexLookupTime |
milisekundy | Czas spędzony w warstwie indeksu fizycznego |
QueryPreparationTime |
milisekundy | Czas spędzony na przygotowaniu zapytania |
RuntimeExecutionTime |
milisekundy | Łączny czas wykonywania zapytania |
VMExecutionTime |
milisekundy | Czas spędzony w środowisku uruchomieniowym zapytań podczas wykonywania zapytania |
OutputDocumentCount |
count | Liczba dokumentów wyjściowych w zestawie wyników |
OutputDocumentSize |
count | Całkowity rozmiar dokumentów wyjściowych w bajtach |
RetrievedDocumentCount |
count | Łączna liczba pobranych dokumentów |
RetrievedDocumentSize |
B | Całkowity rozmiar pobranych dokumentów w bajtach |
IndexHitRatio |
współczynnik [0,1] | Współczynnik liczby dokumentów dopasowanych przez filtr do liczby załadowanych dokumentów |
Zestawy SDK klienta mogą wewnętrznie wysyłać wiele żądań zapytań do obsługi zapytania w ramach każdej partycji. Klient wykonuje więcej niż jedno wywołanie na partycję, jeśli łączna liczba wyników przekracza opcję żądania maksymalnej liczby elementów, jeśli zapytanie przekroczy aprowizowaną przepływność dla partycji, jeśli ładunek zapytania osiągnie maksymalny rozmiar na stronę, lub jeśli zapytanie osiągnie limit czasu przydzielonego systemu. Każde częściowe wykonywanie zapytania zwraca metryki zapytania dla tej strony.
Poniżej przedstawiono kilka przykładowych zapytań i sposób interpretowania niektórych metryk zwracanych z wykonywania zapytania:
Query | Przykładowa metryka | opis |
---|---|---|
SELECT TOP 100 * FROM c |
"RetrievedDocumentCount": 101 |
Liczba pobranych dokumentów wynosi 100+1, aby dopasować się do klauzuli TOP. Czas zapytania jest w większości poświęcany WriteOutputTime na skanowanie i DocumentLoadTime ponieważ jest to skanowanie. |
SELECT TOP 500 * FROM c |
"RetrievedDocumentCount": 501 |
Parametr RetrievedDocumentCount jest teraz wyższy (500+1, aby dopasować do klauzuli TOP). |
SELECT * FROM c WHERE c.N = 55 |
"IndexLookupTime": "00:00:00.0009500" |
Około 0,9 ms jest wydawane w indexLookupTime dla wyszukiwania klucza, ponieważ jest to wyszukiwanie indeksu w pliku /N/? . |
SELECT * FROM c WHERE c.N > 55 |
"IndexLookupTime": "00:00:00.0017700" |
Nieco więcej czasu (1,7 ms) spędził w indexLookupTime podczas skanowania zakresu, ponieważ jest to wyszukiwanie indeksu na /N/? . |
SELECT TOP 500 c.N FROM c |
"IndexLookupTime": "00:00:00.0017700" |
Ten sam czas spędzony na DocumentLoadTime poprzednich zapytaniach, ale niższy DocumentWriteTime , ponieważ projektujemy tylko jedną właściwość. |
SELECT TOP 500 udf.toPercent(c.N) FROM c |
"RuntimeExecutionTime": "00:00:00.2136500" |
Około 213 ms jest wydawane na RuntimeExecutionTime wykonywanie funkcji zdefiniowanej przez użytkownika dla każdej wartości c.N . |
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(c.Name, 'Den') |
"IndexLookupTime": "00:00:00.0006400", "RuntimeExecutionTime": "00:00:00.0074100" |
Około 0,6 ms jest wydawane na IndexLookupTime ./Name/? Większość czasu wykonywania zapytania (~7 ms) w pliku RuntimeExecutionTime . |
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(LOWER(c.Name), 'den') |
"IndexLookupTime": "00:00:00", "RetrievedDocumentCount": 2491, "OutputDocumentCount": 500 |
Zapytanie jest wykonywane jako skanowanie, ponieważ używa LOWER wartości , a zwracane są 500 z 2491 pobranych dokumentów. |
Następne kroki
- Aby dowiedzieć się więcej o obsługiwanych operatorach zapytań SQL i słowach kluczowych, zobacz Zapytanie SQL.
- Aby dowiedzieć się więcej o jednostkach żądań, zobacz Jednostki żądań.
- Aby dowiedzieć się więcej o zasadach indeksowania, zobacz Zasady indeksowania