Hiërarchische partitiesleutels in Azure Cosmos DB

VAN TOEPASSING OP: NoSQL

Azure Cosmos DB distribueert uw gegevens over logische en fysieke partities op basis van uw partitiesleutels ter ondersteuning van horizontaal schalen. Met behulp van hiërarchische partitiesleutels (ook wel subpartitoning genoemd) kunt u maximaal een hiërarchie van drie niveaus configureren voor uw partitiesleutels om de gegevensdistributie verder te optimaliseren en voor een hoger schaalniveau.

Als u tegenwoordig synthetische sleutels gebruikt of als u scenario's hebt waarin partitiesleutels meer dan 20 GB aan gegevens kunnen bevatten, kan subpartitionering helpen. Als u deze functie gebruikt, kunnen voorvoegsels voor logische partitiesleutels groter zijn dan 20 GB en 10.000 aanvraageenheden per seconde (RU/s). Query's per voorvoegsel worden efficiënt gerouteerd naar de subset van partities die de gegevens bevatten.

Uw hiërarchische partitiesleutels kiezen

Als u multitenant-toepassingen hebt, raden we u aan hiërarchische partitiesleutels te gebruiken. Met hiërarchische partities kunt u schalen buiten de limiet voor de logische partitiesleutel van 20 GB. Als uw huidige partitiesleutel of als een enkele partitiesleutel vaak 20 GB bereikt, zijn hiërarchische partities een uitstekende keuze voor uw workload.

Wanneer u uw hiërarchische partitiesleutels kiest, is het belangrijk om rekening te houden met de volgende algemene partitioneringsconcepten:

  • Voor alle containers moet elk niveau van het volledige pad (beginnend met het eerste niveau) van uw hiërarchische partitiesleutel:

    • Een hoge kardinaliteit hebben. De eerste, tweede en derde (indien van toepassing) sleutels van de hiërarchische partitie moeten allemaal een breed scala aan mogelijke waarden hebben.
    • Verbruik van aanvraageenheden (RU) en gegevensopslag gelijkmatig verdelen over alle logische partities. Deze verdeling zorgt voor zelfs RU-verbruik en opslagdistributie over uw fysieke partities.
  • Voor grote, leesintensieve werkbelastingen raden we u aan hiërarchische partitiesleutels te kiezen die regelmatig worden weergegeven in uw query's. Een workload die vaak query's uitvoert om specifieke gebruikerssessies in een multitenant-toepassing uit te filteren, kan bijvoorbeeld profiteren van hiërarchische partitiesleutels van TenantId, UserIden SessionId, in die volgorde. Query's kunnen efficiënt worden gerouteerd naar alleen de relevante fysieke partities door de partitiesleutel op te nemen in het filterpredicaat. Zie het overzicht van partitionering voor meer informatie over het kiezen van partitiesleutels voor leesintensieve workloads.

Voorbeeld van een toepassing

Stel dat u een scenario met meerdere tenants hebt waarin u gebeurtenisgegevens opslaat voor gebruikers in elke tenant. De gebeurtenisgegevens kunnen gebeurtenissen bevatten, waaronder maar niet beperkt tot aanmeldings-, clickstream- of betalingsgebeurtenissen.

In een praktijkscenario kunnen sommige tenants groot worden, met duizenden gebruikers, terwijl de vele andere tenants kleiner zijn en enkele gebruikers hebben. Partitionering door /TenantId kan ertoe leiden dat de opslaglimiet van Azure Cosmos DB van 20 GB voor één logische partitie wordt overschreden. Partitioneren door /UserId alle query's op een tenantoverschrijdende partitie te maken. Beide benaderingen hebben aanzienlijke nadelen.

Het gebruik van een synthetische partitiesleutel die complexiteit combineert TenantId en UserId toevoegt aan de toepassing. Bovendien zijn de synthetische partitiesleutelquery's voor een tenant nog steeds meerdere partities, tenzij alle gebruikers van tevoren bekend en opgegeven zijn.

Met hiërarchische partitiesleutels kunt u eerst partitioneren op TenantIden vervolgens op UserId. Als u verwacht dat de TenantId en UserId combinatie partities produceert die groter zijn dan 20 GB, kunt u zelfs verder naar een ander niveau partitioneren, zoals op SessionId. De totale diepte mag niet groter zijn dan drie niveaus. Wanneer een fysieke partitie groter is dan 50 GB opslagruimte, splitst Azure Cosmos DB de fysieke partitie automatisch, zodat ongeveer de helft van de gegevens zich op één fysieke partitie bevindt en de helft zich op de andere bevindt. In feite betekent subpartitionering dat één TenantId waarde groter kan zijn dan 20 GB aan gegevens en dat gegevens TenantId meerdere fysieke partities kunnen omvatten.

Query's die een TenantIdof beide of beide UserIdTenantId opgeven, worden efficiënt doorgestuurd naar alleen de subset van fysieke partities die de relevante gegevens bevatten. Als u het pad naar de volledige of voorvoegselsubpartitioned partitiesleutel opgeeft, voorkomt u effectief een volledige fan-outquery. Als de container bijvoorbeeld 1000 fysieke partities had, maar een specifieke TenantId waarde slechts op 5 fysieke partities was, wordt de query gerouteerd naar het kleinere aantal relevante fysieke partities.

Item-id in hiërarchie gebruiken

Als uw container een eigenschap heeft met een groot bereik van mogelijke waarden, is de eigenschap waarschijnlijk een uitstekende keuze voor partitiesleutels voor het laatste niveau van uw hiërarchie. Een mogelijk voorbeeld van dit type eigenschap is de item-id. De item-id van de systeemeigenschap bestaat in elk item in uw container. Het toevoegen van de item-id als een ander niveau garandeert dat u kunt schalen buiten de limiet voor de logische partitiesleutel van 20 GB. U kunt buiten deze limiet schalen voor het eerste niveau of voor de eerste en tweede niveaus van sleutels.

U hebt bijvoorbeeld een container voor een workload met meerdere tenants die is gepartitioneerd door TenantId en UserId. Als het mogelijk is om één combinatie van TenantId en UserId meer dan 20 GB te gebruiken, raden we u aan om te partitioneren met behulp van drie niveaus van sleutels en waarin de sleutel op het derde niveau een hoge kardinaliteit heeft. Een voorbeeld van dit scenario is als de sleutel op het derde niveau een GUID is met een natuurlijke hoge kardinaliteit. Het is onwaarschijnlijk dat de combinatie van TenantId, UserIden een GUID groter is dan 20 GB, zodat de combinatie van TenantId en UserId effectief kan worden geschaald buiten 20 GB.

Zie het overzicht van partitionering voor meer informatie over het gebruik van item-id als partitiesleutel.

Aan de slag

Belangrijk

Werken met containers die gebruikmaken van hiërarchische partitiesleutels, wordt alleen ondersteund in de volgende SDK-versies. U moet een ondersteunde SDK gebruiken om nieuwe containers met hiërarchische partitiesleutels te maken en CRUD-bewerkingen (CRUD) of querybewerkingen op de gegevens uit te voeren, te lezen, bij te werken en te verwijderen. Als u een SDK of connector wilt gebruiken die momenteel niet wordt ondersteund, dient u een aanvraag in op ons communityforum.

Zoek de nieuwste preview-versie van elke ondersteunde SDK:

SDK Ondersteunde versies Package Manager-koppeling
.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/

Een container maken met behulp van hiërarchische partitiesleutels

Maak eerst een nieuwe container met behulp van een vooraf gedefinieerde lijst met sleutelpaden voor subpartitionering tot drie diepteniveaus.

U kunt een nieuwe container maken met behulp van een van de volgende opties:

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

Azure Portal

De eenvoudigste manier om een container te maken en hiërarchische partitiesleutels op te geven, is met behulp van Azure Portal.

  1. Meld u aan bij het Azure-portaal.

  2. Ga naar de bestaande azure Cosmos DB for NoSQL-accountpagina.

  3. Selecteer Data Explorer in het linkermenu.

    Schermopname van de pagina voor een nieuw Azure Cosmos DB for NoSQL-account met de menuoptie Data Explorer gemarkeerd.

  4. Selecteer in Data Explorer de optie Nieuwe container.

    Schermopname van de optie Nieuwe container in Data Explorer.

  5. Voer in Nieuwe container voor partitiesleutel in /TenantId. Voer voor de resterende velden een waarde in die overeenkomt met uw scenario.

    Notitie

    We gebruiken /TenantId hier als voorbeeld. U kunt elke sleutel voor het eerste niveau opgeven wanneer u hiërarchische partitiesleutels implementeert in uw eigen containers.

  6. Selecteer Twee keer hiërarchische partitiesleutel toevoegen.

    Schermopname van de knop om een nieuwe hiërarchische partitiesleutel toe te voegen.

  7. Voor de tweede en derde laag van subpartitionering voert u respectievelijk het volgende in /UserId/SessionId .

    Schermopname van een lijst met drie hiërarchische partitiesleutels.

  8. Selecteer OK om de container aan te maken.

SDK

Wanneer u een nieuwe container maakt met behulp van de SDK, definieert u een lijst met sleutelpaden voor subpartitionering tot drie diepteniveaus. Gebruik de lijst met subpartitionsleutels wanneer u de eigenschappen van de nieuwe container configureert.

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

De Azure Resource Manager-sjabloon voor een subpartitioneerde container is bijna identiek aan een standaardcontainer. Het enige belangrijke verschil is de waarde van het properties/partitionKey pad. Zie de azure Resource Manager-sjabloonreferentie voor Azure Cosmos DB voor meer informatie over het maken van een Azure Resource Manager-sjabloonsjabloon voor Azure Cosmos DB.

Configureer het partitionKey object met behulp van de waarden in de volgende tabel om een subpartitioneerde container te maken:

Pad Weergegeven als
paths Lijst met hiërarchische partitiesleutels (maximaal drie diepteniveaus)
kind MultiHash
version 2

Voorbeeld van definitie van partitiesleutel

Stel dat u een hiërarchische partitiesleutel hebt die bestaat uit TenantIdSessionId>UserId>. Het partitionKey object wordt geconfigureerd om alle drie de waarden in de paths eigenschap, een kind waarde van MultiHashen een version waarde van 2.

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

Zie de ContainerPartitionKey-specificatie voor meer informatie over het partitionKey object.

Azure Cosmos DB emulator

U kunt de subpartitioneringsfunctie testen met behulp van de nieuwste versie van de lokale emulator voor Azure Cosmos DB. Als u subpariëring wilt inschakelen voor de emulator, start u de emulator vanuit de installatiemap met de /EnablePreview vlag:

.\CosmosDB.Emulator.exe /EnablePreview

Waarschuwing

De emulator biedt momenteel geen ondersteuning voor alle hiearchische partitiesleutelfuncties als de portal. De emulator biedt momenteel geen ondersteuning voor:

  • Data Explorer gebruiken om containers met hiërarchische partitiesleutels te maken
  • Data Explorer gebruiken om naar items te navigeren en ermee te werken met behulp van hiërarchische partitiesleutels

Zie De Azure Cosmos DB-emulator voor meer informatie.

De SDK's gebruiken om te werken met containers met hiërarchische partitiesleutels

Wanneer u een container hebt met hiërarchische partitiesleutels, gebruikt u de eerder opgegeven versies van de .NET- of Java-SDK's om bewerkingen uit te voeren en query's uit te voeren op die container.

Een item toevoegen aan een container

Er zijn twee opties om een nieuw item toe te voegen aan een container waarvoor hiërarchische partitiesleutels zijn ingeschakeld:

  • Automatische extractie
  • Het pad handmatig opgeven

Automatische extractie

Als u een object doorgeeft met de partitiesleutelwaardeset, kan de SDK automatisch het volledige pad naar de partitiesleutel extraheren.

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

Het pad handmatig opgeven

De PartitionKeyBuilder klasse in de SDK kan een waarde maken voor een eerder gedefinieerd hiërarchisch partitiesleutelpad. Gebruik deze klasse wanneer u een nieuw item toevoegt aan een container waarvoor subpartitionering is ingeschakeld.

Tip

Op schaal kunnen de prestaties worden verbeterd als u het volledige partitiesleutelpad opgeeft, zelfs als de SDK het pad uit het object kan extraheren.

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

Een sleutel/waarde opzoeken (punt lezen) van een item uitvoeren

Sleutel-/waardezoekacties (puntleesbewerkingen) worden uitgevoerd op een manier die vergelijkbaar is met een niet-subpartitioneerde container. Stel dat u een hiërarchische partitiesleutel hebt die bestaat uit TenantIdSessionId>UserId>. De unieke id voor het item is een GUID. Deze wordt weergegeven als een tekenreeks die fungeert als een unieke documenttransactie-id. Als u een punt wilt lezen op één item, geeft u de id eigenschap van het item en de volledige waarde voor de partitiesleutel door, inclusief alle drie de onderdelen van het pad.

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

Een query uitvoeren

De SDK-code die u gebruikt om een query uit te voeren op een subpartitioneerde container, is identiek aan het uitvoeren van een query op een niet-subpartitioneerde container.

Wanneer de query alle waarden van de partitiesleutels in het WHERE filter of in een voorvoegsel van de sleutelhiërarchie opgeeft, stuurt de SDK de query automatisch naar de bijbehorende fysieke partities. Query's die alleen het 'midden' van de hiërarchie bieden, zijn query's tussen partities.

Denk bijvoorbeeld aan een hiërarchische partitiesleutel die bestaat TenantId>>UserIdSessionIduit . De onderdelen van het filter van de query bepalen of de query een query met één partitie, een doelquery voor meerdere partities of een fan-outquery is.

Query Routering
SELECT * FROM c WHERE c.TenantId = 'Microsoft' AND c.UserId = '8411f20f-be3e-416a-a3e7-dcd5a3c1f28b' AND c.SessionId = '0000-11-0000-1111' Gerouteerd naar de enkele logische en fysieke partitie die de gegevens voor de opgegeven waarden van TenantId, UserIden SessionId.
SELECT * FROM c WHERE c.TenantId = 'Microsoft' AND c.UserId = '8411f20f-be3e-416a-a3e7-dcd5a3c1f28b' Alleen gerouteerd naar de doelsubset van logische en fysieke partities die gegevens bevatten voor de opgegeven waarden van TenantId en UserId. Deze query is een doelquery voor meerdere partities die gegevens retourneert voor een specifieke gebruiker in de tenant.
SELECT * FROM c WHERE c.TenantId = 'Microsoft' Wordt alleen doorgestuurd naar de doelsubset van logische en fysieke partities die gegevens bevatten voor de opgegeven waarde van TenantId. Deze query is een doelquery voor meerdere partities die gegevens retourneert voor alle gebruikers in een tenant.
SELECT * FROM c WHERE c.UserId = '8411f20f-be3e-416a-a3e7-dcd5a3c1f28b' Gerouteerd naar alle fysieke partities, wat resulteert in een fan-out crosspartitiequery.
SELECT * FROM c WHERE c.SessionId = '0000-11-0000-1111' Gerouteerd naar alle fysieke partities, wat resulteert in een fan-out crosspartitiequery.

Query met één partitie op een gepartitioneerde container

Hier volgt een voorbeeld van het uitvoeren van een query met alle niveaus van subpartitionering, waardoor de query effectief een query met één partitie wordt.

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

Gerichte query met meerdere partities op een subpartitioneerde container

Hier volgt een voorbeeld van een query met een subset van de niveaus van subpartitionering, waardoor deze query effectief een doelquery met meerdere partities wordt.

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

Beperkingen en bekende problemen

  • Werken met containers die gebruikmaken van hiërarchische partitiesleutels wordt alleen ondersteund in de .NET v3 SDK, in de Java v4 SDK en in de preview-versie van de JavaScript SDK. U moet een ondersteunde SDK gebruiken om nieuwe containers met hiërarchische partitiesleutels te maken en CRUD- of querybewerkingen op de gegevens uit te voeren. Ondersteuning voor andere SDK's, waaronder Python, is momenteel niet beschikbaar.
  • Er zijn beperkingen met verschillende Azure Cosmos DB-connectors (bijvoorbeeld met Azure Data Factory).
  • U kunt hiërarchische partitiesleutels slechts drie lagen diep opgeven.
  • Hiërarchische partitiesleutels kunnen momenteel alleen worden ingeschakeld voor nieuwe containers. U moet partitiesleutelpaden instellen op het moment dat de container is gemaakt en u kunt deze later niet meer wijzigen. Als u hiërarchische partities wilt gebruiken voor bestaande containers, maakt u een nieuwe container met de hiërarchische partitiesleutels die zijn ingesteld en verplaatst u de gegevens met behulp van containerkopieertaken.
  • Hiërarchische partitiesleutels worden momenteel alleen ondersteund voor de API voor NoSQL-accounts. De API's voor MongoDB en Cassandra worden momenteel niet ondersteund.
  • Hiërarchische partitiesleutels worden momenteel niet ondersteund met de functie Machtigingen. U kunt geen machtiging toewijzen aan een gedeeltelijk voorvoegsel van het hiërarchische partitiesleutelpad. Machtigingen kunnen alleen worden toegewezen aan het hele pad naar de logische partitiesleutel. Als u bijvoorbeeld op - >UserIdhebt gepartitioneerd TenantId , kunt u geen machtiging toewijzen die is bedoeld voor een specifieke waarde van TenantId. U kunt echter wel een machtiging voor een partitiesleutel toewijzen als u zowel de waarde voor TenantId als 'UserId'' opgeeft.

Volgende stappen