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
  • Wskazówki 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 LOWERwartoś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