Hierarchiczne klucze partycji w usłudze Azure Cosmos DB

DOTYCZY: NoSQL

Usługa Azure Cosmos DB dystrybuuje dane między partycjami logicznymi i fizycznymi na podstawie kluczy partycji, aby obsługiwać skalowanie w poziomie. Korzystając z hierarchicznych kluczy partycji (nazywanych również podpartiowaniem), można skonfigurować maksymalnie trzypoziomową hierarchię kluczy partycji w celu dalszej optymalizacji dystrybucji danych i wyższego poziomu skalowania.

Jeśli obecnie używasz kluczy syntetycznych lub masz scenariusze, w których klucze partycji mogą przekraczać 20 GB danych, partycjonowanie może pomóc. Jeśli używasz tej funkcji, prefiksy kluczy partycji logicznej mogą przekraczać 20 GB i 10 000 jednostek żądania na sekundę (RU/s). Zapytania według prefiksu są efektywnie kierowane do podzestawu partycji, które przechowują dane.

Wybieranie hierarchicznych kluczy partycji

Jeśli masz aplikacje wielodostępne, zalecamy używanie hierarchicznych kluczy partycji. Partycje hierarchiczne umożliwiają skalowanie poza limit klucza partycji logicznej 20 GB. Jeśli bieżący klucz partycji lub pojedynczy klucz partycji często osiąga 20 GB, partycje hierarchiczne są doskonałym wyborem dla obciążenia.

Podczas wybierania hierarchicznych kluczy partycji należy pamiętać o następujących ogólnych pojęciach dotyczących partycjonowania:

  • Dla wszystkich kontenerów każdy poziom pełnej ścieżki (począwszy od pierwszego poziomu) klucza partycji hierarchicznej powinien:

    • Mają wysoką kardynalność. Pierwsze, drugie i trzecie (jeśli dotyczy) klucze partycji hierarchicznej powinny mieć szeroki zakres możliwych wartości.
    • Równomierne rozłożenie użycia jednostek żądań (RU) i magazynu danych we wszystkich partycjach logicznych. Dzięki temu równomierne użycie jednostek ŻĄDANIA i dystrybucja magazynu między partycjami fizycznymi.
  • W przypadku dużych, dużych obciążeń z dużym obciążeniem zalecamy wybranie hierarchicznych kluczy partycji, które są często wyświetlane w zapytaniach. Na przykład obciążenie, które często uruchamia zapytania w celu odfiltrowania określonych sesji użytkownika w aplikacji wielodostępnej, może korzystać z hierarchicznych kluczy TenantIdpartycji , UserIdi SessionId, w tej kolejności. Zapytania mogą być efektywnie kierowane tylko do odpowiednich partycji fizycznych, uwzględniając klucz partycji w predykacie filtru. Aby uzyskać więcej informacji na temat wybierania kluczy partycji dla obciążeń wymagających odczytu, zobacz omówienie partycjonowania.

Przykładowy przypadek użycia

Załóżmy, że masz scenariusz wielodostępny, w którym przechowujesz informacje o zdarzeniach dla użytkowników w każdej dzierżawie. Informacje o zdarzeniu mogą zawierać wystąpienia zdarzeń, w tym logowania, strumienia kliknięć lub zdarzeń płatności.

W rzeczywistym scenariuszu niektóre dzierżawy mogą rosnąć duże, z tysiącami użytkowników, podczas gdy wiele innych dzierżaw jest mniejszych i ma kilku użytkowników. Partycjonowanie przez /TenantId może prowadzić do przekroczenia limitu magazynu 20 GB usługi Azure Cosmos DB na pojedynczej partycji logicznej. Partycjonowanie według /UserId powoduje, że wszystkie zapytania w dzierżawie są podzielone na partycje. Oba podejścia mają znaczące wady.

Użycie syntetycznego klucza partycji, który łączy TenantId i UserId zwiększa złożoność aplikacji. Ponadto syntetyczne zapytania dotyczące klucza partycji dla dzierżawy są nadal między partycjami, chyba że wszyscy użytkownicy są znani i określeni z wyprzedzeniem.

Za pomocą hierarchicznych kluczy partycji można najpierw podzielić partycje na TenantId, a następnie na UserId. Jeśli oczekujesz, że kombinacja TenantId i UserId spowoduje wygenerowanie partycji przekraczających 20 GB, możesz jeszcze bardziej podzielić partycje na inny poziom, na przykład na .SessionId Ogólna głębokość nie może przekraczać trzech poziomów. Gdy partycja fizyczna przekracza 50 GB magazynu, usługa Azure Cosmos DB automatycznie dzieli partycję fizyczną, tak aby około połowa danych była na jednej partycji fizycznej, a połowa jest na drugiej. Efektywnie dzielenie na części oznacza, że pojedyncza TenantId wartość może przekroczyć 20 GB danych i możliwe TenantId jest, aby dane obejmowały wiele partycji fizycznych.

Zapytania określające TenantIdzarówno , jak TenantId i i UserId, są efektywnie kierowane tylko do podzbioru partycji fizycznych zawierających odpowiednie dane. Efektywne określanie pełnej lub prefiksowej ścieżki klucza partycji podrzędnej pozwala uniknąć pełnego zapytania fan-out. Jeśli na przykład kontener miał 1000 partycji fizycznych, ale określona TenantId wartość była tylko na 5 partycjach fizycznych, zapytanie zostanie przekierowane do mniejszej liczby odpowiednich partycji fizycznych.

Używanie identyfikatora elementu w hierarchii

Jeśli kontener ma właściwość, która ma duży zakres możliwych wartości, właściwość prawdopodobnie jest doskonałym wyborem klucza partycji dla ostatniego poziomu hierarchii. Jednym z możliwych przykładów tej właściwości jest identyfikator elementu. Identyfikator elementu właściwości systemu istnieje w każdym elemencie w kontenerze. Dodanie identyfikatora elementu jako innego poziomu gwarantuje, że można skalować poza limit klucza partycji logicznej 20 GB. Można skalować poza ten limit dla pierwszego poziomu lub dla pierwszego i drugiego poziomu kluczy.

Na przykład może istnieć kontener dla obciążenia wielodostępnego podzielonego na partycje według TenantId i UserId. Jeśli istnieje możliwość użycia pojedynczej kombinacji wartości i UserId przekroczenia TenantId 20 GB, zalecamy partycjonowanie przy użyciu trzech poziomów kluczy, w których klucz trzeciego poziomu ma wysoką kardynalność. Przykładem tego scenariusza jest to, że klucz trzeciego poziomu jest identyfikatorem GUID, który ma naturalnie wysoką kardynalność. Jest mało prawdopodobne, że kombinacja , TenantIdUserIdi identyfikator GUID przekracza 20 GB, więc kombinacja TenantId i UserId może skutecznie skalować ponad 20 GB.

Aby uzyskać więcej informacji na temat używania identyfikatora elementu jako klucza partycji, zobacz omówienie partycjonowania.

Rozpocznij

Ważne

Praca z kontenerami korzystającymi z hierarchicznych kluczy partycji jest obsługiwana tylko w następujących wersjach zestawu SDK. Należy użyć obsługiwanego zestawu SDK, aby utworzyć nowe kontenery z hierarchicznymi kluczami partycji oraz wykonać operacje tworzenia, odczytu, aktualizowania i usuwania (CRUD) lub wykonywania zapytań na danych. Jeśli chcesz użyć zestawu SDK lub łącznika, który nie jest obecnie obsługiwany, zgłoś żądanie na naszym forum społeczności.

Znajdź najnowszą wersję zapoznawcza każdego obsługiwanego zestawu SDK:

SDK Obsługiwane wersje Link menedżera pakietów
.NET SDK 3 >= 3.33.0 https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.33.0/
Java SDK 4 >= 4.42.0 https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/cosmos/azure-cosmos/CHANGELOG.md#4420-2023-03-17/
Zestaw JavaScript SDK w wersji 4 4.0.0 https://www.npmjs.com/package/@azure/cosmos/
Zestaw SDK dla języka Python >= 4.6.0 https://pypi.org/project/azure-cosmos/4.6.0/

Tworzenie kontenera przy użyciu hierarchicznych kluczy partycji

Aby rozpocząć, utwórz nowy kontener przy użyciu wstępnie zdefiniowanej listy ścieżek kluczy partycjonowania do trzech poziomów głębokości.

Nowy kontener można utworzyć przy użyciu jednej z następujących opcji:

  • Azure Portal
  • SDK
  • Szablon usługi Azure Resource Manager
  • Instalowanie i używanie emulatora usługi Azure Cosmos DB do lokalnego programowania i testowania

Azure Portal

Najprostszym sposobem utworzenia kontenera i określenia hierarchicznych kluczy partycji jest użycie witryny Azure Portal.

  1. Zaloguj się w witrynie Azure Portal.

  2. Przejdź do istniejącej strony konta usługi Azure Cosmos DB for NoSQL.

  3. W menu po lewej stronie wybierz pozycję Eksplorator danych.

    Zrzut ekranu przedstawiający stronę nowego konta usługi Azure Cosmos DB for NoSQL z wyróżnioną opcją menu Eksplorator danych.

  4. W Eksploratorze danych wybierz opcję Nowy kontener .

    Zrzut ekranu przedstawiający opcję Nowy kontener w Eksploratorze danych.

  5. W polu Nowy kontener w polu Klucz partycji wprowadź wartość /TenantId. W pozostałych polach wprowadź dowolną wartość zgodną ze scenariuszem.

    Uwaga

    W tym przykładzie użyto /TenantId metody . Podczas implementowania hierarchicznych kluczy partycji we własnych kontenerach można określić dowolny klucz pierwszego poziomu.

  6. Wybierz dwukrotnie pozycję Dodaj hierarchiczny klucz partycji.

    Zrzut ekranu przedstawiający przycisk dodawania nowego hierarchicznego klucza partycji.

  7. W przypadku drugiej i trzeciej warstwy partycjonowania wprowadź odpowiednio wartości /UserId i /SessionId .

    Zrzut ekranu przedstawiający listę trzech hierarchicznych kluczy partycji.

  8. Wybierz przycisk OK, aby utworzyć kontener.

SDK

Podczas tworzenia nowego kontenera przy użyciu zestawu SDK zdefiniuj listę ścieżek kluczy partycjonowania do trzech poziomów głębokości. Podczas konfigurowania właściwości nowego kontenera użyj listy kluczy części podrzędnych.

// List of partition keys, in hierarchical order. You can have up to three levels of keys.
List<string> subpartitionKeyPaths = new List<string> { 
    "/TenantId",
    "/UserId",
    "/SessionId"
};

// Create a container properties object
ContainerProperties containerProperties = new ContainerProperties(
    id: "<container-name>",
    partitionKeyPaths: subpartitionKeyPaths
);

// Create a container that's subpartitioned by TenantId > UserId > SessionId
Container container = await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400);

Szablony usługi Azure Resource Manager

Szablon usługi Azure Resource Manager dla kontenera z podpartycją jest niemal identyczny ze standardowym kontenerem. Jedyną kluczową różnicą jest wartość ścieżki properties/partitionKey . Aby uzyskać więcej informacji na temat tworzenia szablonu usługi Azure Resource Manager dla zasobu usługi Azure Cosmos DB, zobacz dokumentację szablonu usługi Azure Resource Manager dla usługi Azure Cosmos DB.

partitionKey Skonfiguruj obiekt przy użyciu wartości w poniższej tabeli, aby utworzyć kontener z podziałem na części:

Ścieżka Wartość
paths Lista hierarchicznych kluczy partycji (maksymalnie trzy poziomy głębokości)
kind MultiHash
version 2

Przykładowa definicja klucza partycji

Załóżmy na przykład, że masz hierarchiczny klucz partycji składający się z TenantId>>UserIdSessionIdelementu . Obiekt partitionKey zostanie skonfigurowany tak, aby zawierał wszystkie trzy wartości we paths właściwości, kind wartość MultiHashi version wartość 2.

partitionKey: {
  paths: [
    '/TenantId'
    '/UserId'
    '/SessionId'
  ]
  kind: 'MultiHash'
  version: 2
}

Aby uzyskać więcej informacji na temat partitionKey obiektu, zobacz specyfikację ContainerPartitionKey.

Instalowanie i używanie emulatora usługi Azure Cosmos DB do lokalnego programowania i testowania

Funkcję partycjonowania można przetestować przy użyciu najnowszej wersji lokalnego emulatora usługi Azure Cosmos DB. Aby włączyć podparowanie w emulatorze, uruchom emulator z katalogu instalacyjnego z flagą /EnablePreview :

.\CosmosDB.Emulator.exe /EnablePreview

Ostrzeżenie

Emulator nie obsługuje obecnie wszystkich funkcji klucza partycji hiearchical jako portalu. Emulator obecnie nie obsługuje następujących funkcji:

  • Tworzenie kontenerów z hierarchicznymi kluczami partycji za pomocą Eksploratora danych
  • Przechodzenie do elementów za pomocą eksploratora danych i interakcja z nimi przy użyciu hierarchicznych kluczy partycji

Aby uzyskać więcej informacji, zobacz Emulator usługi Azure Cosmos DB.

Używanie zestawów SDK do pracy z kontenerami z hierarchicznymi kluczami partycji

Jeśli masz kontener z hierarchicznymi kluczami partycji, użyj wcześniej określonych wersji zestawów SDK platformy .NET lub Java do wykonywania operacji i wykonywania zapytań w tym kontenerze.

Dodawanie elementu do kontenera

Istnieją dwie opcje dodawania nowego elementu do kontenera z włączonymi hierarchicznymi kluczami partycji:

  • Automatyczne wyodrębnianie
  • Ręczne określanie ścieżki

Automatyczne wyodrębnianie

Jeśli przekażesz obiekt z ustawioną wartością klucza partycji, zestaw SDK będzie mógł automatycznie wyodrębnić pełną ścieżkę klucza partycji.

// Create a new item
UserSession item = new UserSession()
{
    id = "f7da01b0-090b-41d2-8416-dacae09fbb4a",
    TenantId = "Microsoft",
    UserId = "8411f20f-be3e-416a-a3e7-dcd5a3c1f28b",
    SessionId = "0000-11-0000-1111"
};

// Pass in the object, and the SDK automatically extracts the full partition key path
ItemResponse<UserSession> createResponse = await container.CreateItemAsync(item);

Ręczne określanie ścieżki

Klasa PartitionKeyBuilder w zestawie SDK może utworzyć wartość dla wcześniej zdefiniowanej hierarchicznej ścieżki klucza partycji. Ta klasa jest używana podczas dodawania nowego elementu do kontenera z włączoną podpartycją.

Napiwek

Na dużą skalę wydajność może zostać poprawiona, jeśli określisz pełną ścieżkę klucza partycji, nawet jeśli zestaw SDK może wyodrębnić ścieżkę z obiektu.

// Create a new item object
PaymentEvent item = new PaymentEvent()
{
    id = Guid.NewGuid().ToString(),
    TenantId = "Microsoft",
    UserId = "8411f20f-be3e-416a-a3e7-dcd5a3c1f28b",
    SessionId = "0000-11-0000-1111"
};

// Specify the full partition key path when creating the item
PartitionKey partitionKey = new PartitionKeyBuilder()
            .Add(item.TenantId)
            .Add(item.UserId)
            .Add(item.SessionId)
            .Build();

// Create the item in the container
ItemResponse<PaymentEvent> createResponse = await container.CreateItemAsync(item, partitionKey);

Wykonywanie wyszukiwania klucza/wartości (odczyt punktu) elementu

Wyszukiwania klucz/wartość (odczyty punktów) są wykonywane w sposób podobny do kontenera niepartycyjnego. Załóżmy na przykład, że masz hierarchiczny klucz partycji składający się z TenantId>>UserIdSessionIdelementu . Unikatowy identyfikator elementu to identyfikator GUID. Jest reprezentowana jako ciąg, który służy jako unikatowy identyfikator transakcji dokumentu. Aby wykonać odczyt punktu dla pojedynczego elementu, przekaż id właściwość elementu i pełną wartość klucza partycji, w tym wszystkie trzy składniki ścieżki.

// Store the unique identifier
string id = "f7da01b0-090b-41d2-8416-dacae09fbb4a";

// Build the full partition key path
PartitionKey partitionKey = new PartitionKeyBuilder()
    .Add("Microsoft") //TenantId
    .Add("8411f20f-be3e-416a-a3e7-dcd5a3c1f28b") //UserId
    .Add("0000-11-0000-1111") //SessionId
    .Build();

// Perform a point read
ItemResponse<UserSession> readResponse = await container.ReadItemAsync<UserSession>(
    id,
    partitionKey
);

Uruchamianie zapytania

Kod zestawu SDK używany do uruchamiania zapytania w kontenerze z podpartycją jest identyczny z uruchamianiem zapytania w kontenerze niepartycyjnym.

Gdy zapytanie określa wszystkie wartości kluczy partycji w filtrze WHERE lub w prefiksie hierarchii kluczy, zestaw SDK automatycznie kieruje zapytanie do odpowiednich partycji fizycznych. Zapytania, które zapewniają tylko "środek" hierarchii, to zapytania obejmujące wiele partycji.

Rozważmy na przykład hierarchiczny klucz partycji składający się z TenantId>>UserIdSessionIdelementu . Składniki filtru zapytania określają, czy zapytanie jest zapytaniem z jedną partycją, docelowym zapytaniem między partycjami lub zapytaniem fan-out.

Query Routing
SELECT * FROM c WHERE c.TenantId = 'Microsoft' AND c.UserId = '8411f20f-be3e-416a-a3e7-dcd5a3c1f28b' AND c.SessionId = '0000-11-0000-1111' Kierowany do pojedynczej partycji logicznej i fizycznej zawierającej dane dla określonych wartości TenantId, UserIdi SessionId.
SELECT * FROM c WHERE c.TenantId = 'Microsoft' AND c.UserId = '8411f20f-be3e-416a-a3e7-dcd5a3c1f28b' Kierowany do tylko docelowego podzestawu partycji logicznych i fizycznych, które zawierają dane dla określonych wartości TenantId i UserId. To zapytanie jest docelowym zapytaniem między partycjami, które zwraca dane dla określonego użytkownika w dzierżawie.
SELECT * FROM c WHERE c.TenantId = 'Microsoft' Kierowany do tylko docelowego podzestawu partycji logicznych i fizycznych, które zawierają dane dla określonej wartości TenantId. To zapytanie jest docelowym zapytaniem między partycjami, które zwraca dane dla wszystkich użytkowników w dzierżawie.
SELECT * FROM c WHERE c.UserId = '8411f20f-be3e-416a-a3e7-dcd5a3c1f28b' Kierowany do wszystkich partycji fizycznych, co powoduje utworzenie zapytania obejmującego wiele partycji.
SELECT * FROM c WHERE c.SessionId = '0000-11-0000-1111' Kierowany do wszystkich partycji fizycznych, co powoduje utworzenie zapytania obejmującego wiele partycji.

Zapytanie z jedną partycją w kontenerze podzielonym na części

Oto przykład uruchamiania zapytania zawierającego wszystkie poziomy partycjonowania, co skutecznie czyni zapytanie zapytaniem z jedną partycją.

// Define a single-partition query that specifies the full partition key path
QueryDefinition query = new QueryDefinition(
    "SELECT * FROM c WHERE c.TenantId = @tenant-id AND c.UserId = @user-id AND c.SessionId = @session-id")
    .WithParameter("@tenant-id", "Microsoft")
    .WithParameter("@user-id", "8411f20f-be3e-416a-a3e7-dcd5a3c1f28b")
    .WithParameter("@session-id", "0000-11-0000-1111");

// Retrieve an iterator for the result set
using FeedIterator<PaymentEvent> results = container.GetItemQueryIterator<PaymentEvent>(query);

while (results.HasMoreResults)
{
    FeedResponse<UserSession> resultsPage = await resultSet.ReadNextAsync();
    foreach(UserSession result in resultsPage)
    {
        // Process result
    }
}

Docelowe zapytanie obejmujące wiele partycji w kontenerze podzielonym na części

Oto przykład zapytania zawierającego podzbiór poziomów partycjonowania, co skutecznie czyni to zapytanie zapytaniem docelowym zapytaniem z wieloma partycjami.

// Define a targeted cross-partition query specifying prefix path[s]
QueryDefinition query = new QueryDefinition(
    "SELECT * FROM c WHERE c.TenantId = @tenant-id")
    .WithParameter("@tenant-id", "Microsoft")

// Retrieve an iterator for the result set
using FeedIterator<PaymentEvent> results = container.GetItemQueryIterator<PaymentEvent>(query);

while (results.HasMoreResults)
{
    FeedResponse<UserSession> resultsPage = await resultSet.ReadNextAsync();
    foreach(UserSession result in resultsPage)
    {
        // Process result
    }
}

Ograniczenia i znane problemy

  • Praca z kontenerami korzystającymi z hierarchicznych kluczy partycji jest obsługiwana tylko w zestawie SDK platformy .NET w wersji 3, w zestawie SDK języka Java w wersji 4 i w wersji zapoznawczej zestawu SDK języka JavaScript. Należy użyć obsługiwanego zestawu SDK, aby utworzyć nowe kontenery z hierarchicznymi kluczami partycji oraz wykonać operacje CRUD lub wykonywania zapytań na danych. Obsługa innych zestawów SDK, w tym języka Python, nie jest obecnie dostępna.
  • Istnieją ograniczenia dotyczące różnych łączników usługi Azure Cosmos DB (na przykład w usłudze Azure Data Factory).
  • Można określić hierarchiczne klucze partycji tylko do trzech warstw w głębi systemu.
  • Hierarchiczne klucze partycji można obecnie włączać tylko w nowych kontenerach. Należy ustawić ścieżki klucza partycji w momencie tworzenia kontenera i nie można ich później zmienić. Aby używać partycji hierarchicznych w istniejących kontenerach, utwórz nowy kontener z ustawionymi hierarchicznymi kluczami partycji i przenieś dane przy użyciu zadań kopiowania kontenera.
  • Hierarchiczne klucze partycji są obecnie obsługiwane tylko dla interfejsu API dla kont NoSQL. Interfejsy API dla baz danych MongoDB i Cassandra nie są obecnie obsługiwane.
  • Hierarchiczne klucze partycji nie są obecnie obsługiwane za pomocą funkcji Uprawnienia. Nie można przypisać uprawnienia do częściowego prefiksu ścieżki klucza partycji hierarchicznej. Uprawnienia można przypisać tylko do całej ścieżki klucza partycji logicznej. Na przykład jeśli masz partycjonowane według TenantId — >UserId, nie możesz przypisać uprawnienia, które jest dla określonej wartości TenantId. Można jednak przypisać uprawnienie dla klucza partycji, jeśli określisz zarówno wartość dla TenantId , jak i "UserId".

Następne kroki