Hierarkiska partitionsnycklar i Azure Cosmos DB

GÄLLER FÖR: NoSQL

Azure Cosmos DB distribuerar dina data över logiska och fysiska partitioner baserat på dina partitionsnycklar för att stödja horisontell skalning. Genom att använda hierarkiska partitionsnycklar (kallas även underpartitonering) kan du konfigurera upp till en hierarki på tre nivåer för dina partitionsnycklar för att ytterligare optimera datadistributionen och för en högre skalningsnivå.

Om du använder syntetiska nycklar i dag, har scenarier där partitionsnycklar kan överskrida 20 GB data, eller vill se till att varje klientorganisations dokument mappas till sin egen logiska partition, kan underpartitionering hjälpa. Om du använder den här funktionen kan de logiska partitionsnyckelprefixen överskrida 20 GB och 10 000 enheter för begäranden per sekund (RU/s). Frågor efter prefix dirigeras effektivt till den delmängd av partitioner som innehåller data.

Välja dina hierarkiska partitionsnycklar

Om du har program med flera klienter och för närvarande isolerar klientorganisationer efter partitionsnyckel kan hierarkiska partitioner gynna dig. Med hierarkiska partitioner kan du skala bortom den logiska partitionsnyckelgränsen på 20 GB och är en bra lösning om du vill se till att vart och ett av klienternas dokument kan skalas oändligt. Om den aktuella partitionsnyckeln eller om en enskild partitionsnyckel ofta når 20 GB är hierarkiska partitioner ett bra val för din arbetsbelastning.

Beroende på vilken typ av arbetsbelastning du har och hur kardinal din nyckel på första nivån är kan det dock finnas några kompromisser som vi tar upp på djupet på sidan med hierarkiska partitionsscenarier.

När du väljer varje nivå av din hierarkiska partitionsnyckel är det viktigt att ha följande allmänna partitioneringsbegrepp i åtanke och förstå hur var och en kan påverka din arbetsbelastning:

  • För alla containrar bör varje nivå av den fullständiga sökvägen (från och med den första nivån) för den hierarkiska partitionsnyckeln:

    • Ha hög kardinalitet. De första, andra och tredje (om tillämpligt) nycklarna för den hierarkiska partitionen bör alla ha ett brett utbud av möjliga värden.

      • Om du har låg kardinalitet på den första nivån i den hierarkiska partitionsnyckeln begränsas alla skrivåtgärder vid tidpunkten för inmatningen till bara en fysisk partition tills den når 50 GB och delas upp i två fysiska partitioner. Anta till exempel att din första nivånyckel är på TenantId och bara har 5 unika klienter. Var och en av dessa klientorganisationers åtgärder begränsas till bara en fysisk partition, vilket begränsar dataflödesförbrukningen till precis vad som finns på den fysiska partitionen. Det beror på att hierarkiska partitioner optimerar för alla dokument med samma nyckel på första nivån som ska samlas på samma fysiska partition för att undvika fullständiga frågor.
      • Även om detta kan vara okej för arbetsbelastningar där vi gör en engångsinmatning av alla våra klientorganisationers data och följande åtgärder främst är läsintensiva efteråt, kan detta vara endealiskt för arbetsbelastningar där dina affärskrav omfattar inmatning av data inom en viss tid. Om du till exempel har strikta affärskrav för att undvika svarstider är det maximala dataflöde som din arbetsbelastning teoretiskt sett kan uppnå för att mata in data antalet fysiska partitioner * 10 000. Om din toppnivånyckel har låg kardinalitet är antalet fysiska partitioner sannolikt 1, såvida det inte finns tillräckligt med data för att nivå 1-nyckeln ska spridas över flera partitioner efter delningar som kan ta mellan 4 och 6 timmar att slutföra.
    • Sprida ru-förbrukning (request unit) och datalagring jämnt över alla logiska partitioner. Den här spridningen säkerställer även RU-förbrukning och lagringsdistribution över dina fysiska partitioner.

      • Om du väljer en nyckel på första nivån som verkar ha hög kardinalitet som UserId, men i praktiken utför din arbetsbelastning åtgärder på bara en specifik UserId, kommer du sannolikt att stöta på en frekvent partition eftersom alla dina åtgärder begränsas till bara en eller några fysiska partitioner.
  • Läsintensiva arbetsbelastningar: Vi rekommenderar att du väljer hierarkiska partitionsnycklar som visas ofta i dina frågor.

    • Till exempel kan en arbetsbelastning som ofta kör frågor för att filtrera bort specifika användarsessioner i ett program med flera klientorganisationer dra nytta av hierarkiska partitionsnycklar för TenantId, UserIdoch SessionId, i den ordningen. Frågor kan effektivt dirigeras till endast relevanta fysiska partitioner genom att inkludera partitionsnyckeln i filterpredikatet. Mer information om hur du väljer partitionsnycklar för läsintensiva arbetsbelastningar finns i partitioneringsöversikten.
  • Skrivintensiva arbetsbelastningar: Vi rekommenderar att du använder ett högt kardinalvärde för den första nivån av din hierarkiska partitionsnyckel. Hög kardinalitet innebär att den första nivåns nyckel (och efterföljande nivåer också) har minst tusentals unika värden och fler unika värden än antalet fysiska partitioner.

    • Anta till exempel att vi har en arbetsbelastning som isolerar klienter efter partitionsnyckel och har några stora klienter som är mer skrivintensiva än andra. I dag slutar Azure Cosmos DB att mata in data på valfritt partitionsnyckelvärde om det överskrider 20 GB data. I den här arbetsbelastningen är Microsoft och Contoso stora klienter och vi förväntar oss att den växer mycket snabbare än våra andra klienter. För att undvika risken för att inte kunna mata in data för dessa klientorganisationer gör hierarkiska partitionsnycklar att vi kan skala dessa klienter över gränsen på 20 GB. Vi kan lägga till fler nivåer som UserId och SessionId för att säkerställa högre skalbarhet mellan klienter.

    • För att säkerställa att din arbetsbelastning kan hantera skrivningar för alla dokument med samma nyckel på första nivån bör du överväga att använda objekt-ID som en nyckel på andra eller tredje nivån.

    • Om din första nivå inte har hög kardinalitet och du når gränsen på 20 GB logisk partition på partitionsnyckeln i dag föreslår vi att du använder en syntetisk partitionsnyckel i stället för en hierarkisk partitionsnyckel.

Exempel på användningsfall

Anta att du har ett scenario med flera klienter där du lagrar händelseinformation för användare i varje klientorganisation. Händelseinformationen kan ha händelsehändelser, inklusive men inte begränsat till inloggning, klickström eller betalningshändelser.

I ett verkligt scenario kan vissa klienter växa sig stora, med tusentals användare, medan de många andra klienterna är mindre och har några få användare. Partitionering efter /TenantId kan leda till att azure Cosmos DB-lagringsgränsen på 20 GB överskrids på en enda logisk partition. Partitionering efter /UserId gör att alla frågor på en klientorganisation korspartitioneras. Båda metoderna har betydande nackdelar.

Använda en syntetisk partitionsnyckel som kombinerar TenantId och UserId lägger till komplexitet i programmet. Dessutom är de syntetiska partitionsnyckelfrågorna för en klientorganisation fortfarande korspartitionerade, såvida inte alla användare är kända och angivna i förväg.

Om din arbetsbelastning har klienter med ungefär samma arbetsbelastningsmönster kan hierarkisk partitionsnyckel hjälpa. Med hierarkiska partitionsnycklar kan du partitioneras först på TenantIdoch sedan på UserId. Om du förväntar TenantId dig att kombinationen och UserId ska producera partitioner som överskrider 20 GB kan du till och med partitioneras längre ned till en annan nivå, till exempel på SessionId. Det totala djupet får inte överstiga tre nivåer. När en fysisk partition överskrider 50 GB lagringsutrymme delar Azure Cosmos DB automatiskt upp den fysiska partitionen så att ungefär hälften av data finns på en fysisk partition och hälften är på den andra. I praktiken innebär underpartitionering att ett enda TenantId värde kan överstiga 20 GB data, och det är möjligt för TenantId data att sträcka sig över flera fysiska partitioner.

Frågor som anger antingen TenantId, eller både TenantId och och UserId, dirigeras effektivt till endast den delmängd av fysiska partitioner som innehåller relevanta data. Om du anger den fullständiga partitionsnyckelsökvägen eller prefixets underpartitionerade sökväg undviker du i praktiken en fullständig utfläkt fråga. Om containern till exempel hade 1 000 fysiska partitioner, men ett specifikt TenantId värde bara fanns på 5 fysiska partitioner, dirigeras frågan till det mindre antalet relevanta fysiska partitioner.

Använda objekt-ID i hierarkin

Om containern har en egenskap som har ett stort antal möjliga värden är egenskapen förmodligen ett bra partitionsnyckelval för den sista nivån i hierarkin. Ett möjligt exempel på den här typen av egenskap är objekt-ID :t. Systemegenskapens objekt-ID finns i varje objekt i containern. Om du lägger till objekt-ID:t som en annan nivå kan du skala över den logiska partitionsnyckelgränsen på 20 GB. Du kan skala över den här gränsen för den första nivån eller för den första och andra nivån av nycklar.

Du kan till exempel ha en container för en arbetsbelastning med flera klientorganisationer som partitioneras av TenantId och UserId. Om det är möjligt för en enskild kombination av TenantId och UserId överskrider 20 GB rekommenderar vi att du partitioneras med hjälp av tre nivåer av nycklar och där nyckeln på tredje nivån har hög kardinalitet. Ett exempel på det här scenariot är om nyckeln på tredje nivån är ett GUID som har naturligt hög kardinalitet. Det är osannolikt att kombinationen av TenantId, UserIdoch ett GUID överskrider 20 GB, så kombinationen av TenantId och UserId kan effektivt skalas över 20 GB.

Mer information om hur du använder objekt-ID som partitionsnyckel finns i partitioneringsöversikten.

Kom igång

Viktigt!

Att arbeta med containrar som använder hierarkiska partitionsnycklar stöds endast i följande SDK-versioner. Du måste använda en SDK som stöds för att skapa nya containrar med hierarkiska partitionsnycklar och för att kunna skapa, läsa, uppdatera och ta bort (CRUD) eller frågeåtgärder på data. Om du vill använda en SDK eller anslutningsprogram som för närvarande inte stöds kan du skicka en begäran i vårt communityforum.

Hitta den senaste förhandsversionen av varje SDK som stöds:

SDK Versioner som stöds Pakethanterarens länk
.NET SDK v3 >= 3.33.0 https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.33.0/
Java SDK v4 >= 4.42.0 https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/cosmos/azure-cosmos/CHANGELOG.md#4420-2023-03-17/
JavaScript SDK v4 4.0.0 https://www.npmjs.com/package/@azure/cosmos/
Python SDK >= 4.6.0 https://pypi.org/project/azure-cosmos/4.6.0/

Skapa en container med hjälp av hierarkiska partitionsnycklar

Kom igång genom att skapa en ny container med hjälp av en fördefinierad lista över underpartitioneringsnyckelsökvägar på upp till tre djupnivåer.

Du kan skapa en ny container med något av följande alternativ:

  • Azure Portal
  • SDK
  • Azure Resource Manager-mall
  • Azure Cosmos DB-emulator

Azure Portal

Det enklaste sättet att skapa en container och ange hierarkiska partitionsnycklar är med hjälp av Azure Portal.

  1. Logga in på Azure-portalen.

  2. Gå till den befintliga kontosidan för Azure Cosmos DB för NoSQL.

  3. Välj Datautforskaren på den vänstra menyn.

    Skärmbild som visar sidan för ett nytt Azure Cosmos DB för NoSQL-konto med menyalternativet Datautforskaren markerat.

  4. I Datautforskaren väljer du alternativet Ny container.

    Skärmbild av alternativet Ny container i Datautforskaren.

  5. I Ny container för Partitionsnyckel anger du /TenantId. För de återstående fälten anger du ett värde som matchar ditt scenario.

    Kommentar

    Vi använder /TenantId som exempel här. Du kan ange valfri nyckel för den första nivån när du implementerar hierarkiska partitionsnycklar på dina egna containrar.

  6. Välj Lägg till hierarkisk partitionsnyckel två gånger.

    Skärmbild av knappen för att lägga till en ny hierarkisk partitionsnyckel.

  7. För den andra och tredje nivån av underpartitionering anger du /UserId /SessionId respektive.

    Skärmbild av en lista med tre hierarkiska partitionsnycklar.

  8. Skapa behållare genom att välja OK.

SDK

När du skapar en ny container med hjälp av SDK definierar du en lista över underpartitioneringsnyckelsökvägar på upp till tre djupnivåer. Använd listan med underpartitionsnycklar när du konfigurerar egenskaperna för den nya containern.

// 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);

Azure Resource Manager-mallar

Azure Resource Manager-mallen för en underpartitionerad container är nästan identisk med en standardcontainer. Den enda viktiga skillnaden är värdet för properties/partitionKey sökvägen. Mer information om hur du skapar en Azure Resource Manager-mall för en Azure Cosmos DB-resurs finns i mallreferensen för Azure Resource Manager för Azure Cosmos DB.

Konfigurera objektet partitionKey med hjälp av värdena i följande tabell för att skapa en underpartitionerad container:

Sökväg Värde
paths Lista över hierarkiska partitionsnycklar (max tre djupnivåer)
kind MultiHash
version 2

Exempel på definition av partitionsnyckel

Anta till exempel att du har en hierarkisk partitionsnyckel som består av TenantIdSessionId>UserId>. Objektet partitionKey skulle konfigureras för att inkludera alla tre värdena i paths egenskapen, värdet kind MultiHash, och värdet version 2.

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

Mer information om objektet finns i partitionKey ContainerPartitionKey-specifikationen.

Azure Cosmos DB-emulator

Du kan testa underpartitioneringsfunktionen med hjälp av den senaste versionen av den lokala emulatorn för Azure Cosmos DB. Starta emulatorn från installationskatalogen med /EnablePreview flaggan för att aktivera underparitionering på emulatorn:

.\CosmosDB.Emulator.exe /EnablePreview

Varning

Emulatorn stöder för närvarande inte alla hiearkiska partitionsnyckelfunktioner som portalen. Emulatorn stöder för närvarande inte:

  • Använda Datautforskaren för att skapa containrar med hierarkiska partitionsnycklar
  • Använda Datautforskaren för att navigera till och interagera med objekt med hjälp av hierarkiska partitionsnycklar

Mer information finns i Azure Cosmos DB-emulatorn.

Använd SDK:erna för att arbeta med containrar som har hierarkiska partitionsnycklar

När du har en container som har hierarkiska partitionsnycklar använder du tidigare angivna versioner av .NET- eller Java-SDK:erna för att utföra åtgärder och köra frågor på containern.

Lägga till ett objekt i en container

Det finns två alternativ för att lägga till ett nytt objekt i en container med hierarkiska partitionsnycklar aktiverade:

  • Automatisk extrahering
  • Ange sökvägen manuellt

Automatisk extrahering

Om du skickar in ett objekt med partitionsnyckelns värdeuppsättning kan SDK:et automatiskt extrahera den fullständiga partitionsnyckelsökvägen.

// Create a new item
UserSession item = new UserSession()
{
    id = "f7da01b0-090b-41d2-8416-dacae09fbb4a",
    TenantId = "Microsoft",
    UserId = "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
    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);

Ange sökvägen manuellt

Klassen PartitionKeyBuilder i SDK kan konstruera ett värde för en tidigare definierad hierarkisk partitionsnyckelsökväg. Använd den här klassen när du lägger till ett nytt objekt i en container som har underpartitionering aktiverat.

Dricks

I stor skala kan prestanda förbättras om du anger den fullständiga partitionsnyckelsökvägen, även om SDK:t kan extrahera sökvägen från objektet.

// Create a new item object
PaymentEvent item = new PaymentEvent()
{
    id = Guid.NewGuid().ToString(),
    TenantId = "Microsoft",
    UserId = "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
    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);

Utföra ett nyckel-/värde-uppslag (punktläsning) för ett objekt

Nyckel-/värdesökningar (punktläsningar) utförs på ett sätt som liknar en container som inte är en underpartitionerad container. Anta till exempel att du har en hierarkisk partitionsnyckel som består av TenantIdSessionId>UserId>. Den unika identifieraren för objektet är ett GUID. Den representeras som en sträng som fungerar som en unik dokumenttransaktionsidentifierare. Om du vill utföra en punkt som lästs på ett enda objekt skickar du in id egenskapen för objektet och det fullständiga värdet för partitionsnyckeln, inklusive alla tre komponenterna i sökvägen.

// 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("00aa00aa-bb11-cc22-dd33-44ee44ee44ee") //UserId
    .Add("0000-11-0000-1111") //SessionId
    .Build();

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

Köra en fråga

SDK-koden som du använder för att köra en fråga på en underpartitionerad container är identisk med att köra en fråga på en container som inte är underpartitionerad.

När frågan anger alla värden för partitionsnycklarna i WHERE filtret eller i ett prefix i nyckelhierarkin dirigerar SDK:t automatiskt frågan till motsvarande fysiska partitioner. Frågor som endast tillhandahåller "mitten" av hierarkin är frågor mellan partitioner.

Tänk dig till exempel en hierarkisk partitionsnyckel som består av TenantIdSessionId>UserId>. Komponenterna i frågans filter avgör om frågan är en fråga med en partition, en riktad fråga mellan partitioner eller en utspringad fråga.

Fråga Routning
SELECT * FROM c WHERE c.TenantId = 'Microsoft' AND c.UserId = '00aa00aa-bb11-cc22-dd33-44ee44ee44ee' AND c.SessionId = '0000-11-0000-1111' Dirigerad till den enda logiska och fysiska partitionen som innehåller data för de angivna värdena TenantId, UserIdoch SessionId.
SELECT * FROM c WHERE c.TenantId = 'Microsoft' AND c.UserId = '00aa00aa-bb11-cc22-dd33-44ee44ee44ee' Dirigeras endast till den riktade delmängden av logiska och fysiska partitioner som innehåller data för de angivna värdena TenantId för och UserId. Den här frågan är en riktad fråga mellan partitioner som returnerar data för en specifik användare i klientorganisationen.
SELECT * FROM c WHERE c.TenantId = 'Microsoft' Dirigeras endast till den riktade delmängden av logiska och fysiska partitioner som innehåller data för det angivna värdet TenantId. Den här frågan är en riktad fråga mellan partitioner som returnerar data för alla användare i en klientorganisation.
SELECT * FROM c WHERE c.UserId = '00aa00aa-bb11-cc22-dd33-44ee44ee44ee' Dirigeras till alla fysiska partitioner, vilket resulterar i en utskärmad korspartitionsfråga.
SELECT * FROM c WHERE c.SessionId = '0000-11-0000-1111' Dirigeras till alla fysiska partitioner, vilket resulterar i en utskärmad korspartitionsfråga.

Fråga med en partition i en underpartitionerad container

Här är ett exempel på hur du kör en fråga som innehåller alla nivåer av underpartitionering, vilket effektivt gör frågan till en fråga med en partition.

// 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", "00aa00aa-bb11-cc22-dd33-44ee44ee44ee")
    .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
    }
}

Riktad fråga med flera partitioner i en underpartitionerad container

Här är ett exempel på en fråga som innehåller en delmängd av nivåerna för underpartitionering, vilket effektivt gör den här frågan till en riktad fråga med flera partitioner.

// 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
    }
}

Begränsningar och kända problem

  • Att arbeta med containrar som använder hierarkiska partitionsnycklar stöds endast i .NET v3 SDK, i Java v4 SDK, i Python SDK och i förhandsversionen av JavaScript SDK. Du måste använda en SDK som stöds för att skapa nya containrar som har hierarkiska partitionsnycklar och för att utföra CRUD- eller frågeåtgärder på data. Stöd för andra SDK:er, inklusive Python, är inte tillgängligt för närvarande.
  • Det finns begränsningar med olika Azure Cosmos DB-anslutningsappar (till exempel med Azure Data Factory).
  • Du kan ange hierarkiska partitionsnycklar endast upp till tre lager på djupet.
  • Hierarkiska partitionsnycklar kan för närvarande endast aktiveras på nya containrar. Du måste ange partitionsnyckelsökvägar när containern skapas och du kan inte ändra dem senare. Om du vill använda hierarkiska partitioner på befintliga containrar skapar du en ny container med de hierarkiska partitionsnycklarna inställda och flyttar data med hjälp av containerkopieringsjobb.
  • Hierarkiska partitionsnycklar stöds för närvarande endast för API:et för NoSQL-konton. API:erna för MongoDB och Cassandra stöds inte för närvarande.
  • Hierarkiska partitionsnycklar stöds för närvarande inte med funktionen användare och behörigheter. Du kan inte tilldela en behörighet till ett partiellt prefix för den hierarkiska partitionsnyckelsökvägen. Behörigheter kan bara tilldelas till hela sökvägen till den logiska partitionsnyckeln. Om du till exempel har partitionerat av TenantId – >UserIdkan du inte tilldela en behörighet som är för ett specifikt värde på TenantId. Du kan dock tilldela en behörighet för en partitionsnyckel om du anger både värdet för TenantId och "UserId".

Nästa steg