Optimierung der Leistung in Azure Cosmos DB: Beste Praktiken und Tipps

Bei der Arbeit mit einer Datenbank ist die Optimierung entscheidend für die Leistung und Effizienz der Anwendung. Ebenso ist die Optimierung in Azure Cosmos DB entscheidend, um die Effizienz zu maximieren, die Kosten zu minimieren und sicherzustellen, dass Ihre Anwendung effektiv skalierbar ist. Im Folgenden finden Sie einige der besten Praktiken mit Codebeispielen zur Optimierung der Leistung in Azure Cosmos DB.

1. Auswahl des richtigen Partitionierungsschlüssels

Die Wahl eines geeigneten Partitionierungsschlüssels ist entscheidend für verteilte Datenbanken wie Cosmos DB. Ein guter Partitionierungsschlüssel stellt sicher, dass die Daten gleichmäßig auf die Partitionen verteilt sind, wodurch Hotspots reduziert und die Leistung verbessert wird.

Die Auswahl eines Partitionierungsschlüssels ist einfach, aber sehr wichtig in der Entwurfsphase in Azure Cosmos DB. Sobald wir den Partitionierungsschlüssel auswählen, ist es nicht möglich, ihn an Ort und Stelle zu ändern.

Beste Praxis

  • Wählen Sie einen Partitionierungsschlüssel mit hoher Kardinalität (viele eindeutige Werte).
  • Stellen Sie sicher, dass Lese- und Schreibvorgänge gleichmäßig verteilt sind.
  • Halten Sie verwandte Daten zusammen, um Abfragen über Partitionen hinweg zu minimieren.

Beispiel: Erstellen eines Containers mit einem optimalen Partitionierungsschlüssel

C#

 

var database = await cosmosClient.CreateDatabaseIfNotExistsAsync("YourDatabase");
var containerProperties = new ContainerProperties
{
    Id = "myContainer",
    PartitionKeyPath = "/customerId"  // Partition key selected to ensure balanced distribution
}; 

// Erstellen Sie den Container mit 400 RU/s bereitgestelltem Durchsatz
var container = await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400);

2. Richtige Indizierung verwenden

In Azure Cosmos DB werden standardmäßig Indizes auf alle Eigenschaften angewendet, was vorteilhaft sein kann, aber zu erhöhten Speicher- und RU/s-Kosten führen kann. Zur Verbesserung der Abfrageleistung und Minimierung der Kosten sollte die Indizierungspolitik angepasst werden. Cosmos DB unterstützt drei Arten von Indizes: Bereichsindizes, Raumindizes und Verbundindizes. Verwenden Sie den richtigen Typ weise.

Beste Praxis

  • Unerwünschte Felder von der Indizierung ausschließen.
  • Verwenden Sie Verbundindizes für Mehrfeldabfragen.

Beispiel: Benutzerdefinierte Indizierungspolitik

C#

 

{
    "indexingPolicy": {
        "automatic": true,
        "indexingMode": "consistent",  // Can use 'none' or 'lazy' to reduce write costs
        "includedPaths": [
            {
                "path": "/orderDate/?",  // Only index specific fields like orderDate
                "indexes": [
                    {
                        "kind": "Range",
                        "dataType": "Number"
                    }
                ]
            }
        ],
        "excludedPaths": [
            {
                "path": "/largeDataField/*"  // Exclude large fields not used in queries
            }
        ]
    }
}

Beispiel: Hinzufügen eines Verbundindexes für optimierte Abfragen

C#

 

{
    "indexingPolicy": {
        "compositeIndexes": [
            [
                { "path": "/lastName", "order": "ascending" },
                { "path": "/firstName", "order": "ascending" }
            ]
        ]
    }
}

Weitere Informationen zu den Indextypen finden Sie hier.

3. Abfragen optimieren

Effiziente Abfragen sind entscheidend für die Minimierung der Anforderungseinheiten (RU/s) und die Verbesserung der Leistung in Azure Cosmos DB. Die RU/s-Kosten hängen von der Komplexität und Größe der Abfrage ab.

Die Verwendung von Bulk-Executoren kann die Kosten weiter reduzieren, indem die verbrauchten RUs pro Operation verringert werden. Diese Optimierung hilft dabei, den RU-Verbrauch effektiv zu steuern und die Gesamtkosten Ihrer Cosmos DB zu senken.

Best Practice

  • Verwenden Sie SELECT-Abfragenin begrenztem Umfang, und rufen Sie nur notwendige Eigenschaften ab.
  • Vermeiden Sie Abfragen über Partitionen hinweg, indem Sie den Partitionierungsschlüssel in Ihrer Abfrage angeben.
  • Verwenden Sie Filter auf indizierten Feldern, um die Abfragekosten zu senken.

Beispiel: Kundenrecord abrufen

C#

 

var query = new QueryDefinition("SELECT c.firstName, c.lastName FROM Customers c WHERE c.customerId = @customerId")
    .WithParameter("@customerId", "12345");

var iterator = container.GetItemQueryIterator<Customer>(query, requestOptions: new QueryRequestOptions
{
    PartitionKey = new PartitionKey("12345")  // Provide partition key to avoid cross-partition query
});

while (iterator.HasMoreResults)
{
    var response = await iterator.ReadNextAsync();
    foreach (var customer in response)
    {
        Console.WriteLine($"{customer.firstName} {customer.lastName}");
    }
}

4. Feinabstimmung der Konsistenzstufen

Die Konsistenzstufen definieren spezifische Betriebsmodi, die darauf ausgelegt sind, geschwindigkeitsbezogene Garantien zu erfüllen. Es gibt fünf Konsistenzstufen (Stark, Begrenzte Veralterung, Sitzung, Konsistenter Präfix und Letztendlich) in Cosmos DB. Jede Konsistenzstufe hat Auswirkungen auf Latenz, Verfügbarkeit und Durchsatz.

Best Practice

  • Verwenden Sie Sitzungskonsistenz für die meisten Szenarien, um Leistung und Datenkonsistenz auszubalancieren.
  • Starke Konsistenz garantiert Datenkonsistenz, erhöht jedoch RU/s und Latenz.

Beispiel: Konsistenzstufe festlegen

C#

 

var cosmosClient = new CosmosClient(
    "",
    "",
    new CosmosClientOptions
    {
        // Setzen Sie die Konsistenz auf "Sitzung" für ausgewogene Leistung
		ConsistencyLevel = ConsistencyLevel.Session      
});

Erfahren Sie mehr über die Konsistenzstufe hier.

5. Verwenden Sie die bereitgestellte Durchsatzmenge (RU/s) und die automatische Skalierung klug

Die Bereitstellung von Durchsatz ist ein Schlüsselfaktor für die Erreichung von Kosteneffizienz und optimaler Leistung in Azure Cosmos DB. Der Dienst ermöglicht es Ihnen, den Durchsatz auf zwei Arten zu konfigurieren:

  • Feste RU/s: Ein vordefinierter, konstanter Wert der Anforderungseinheiten pro Sekunde (RU/s), geeignet für Workloads mit konstanten Leistungsanforderungen.
  • Auto-Scale: Eine dynamische Option, die den Durchsatz automatisch anhand von Arbeitslastschwankungen anpasst, Skalierbarkeit bietet und gleichzeitig eine Überbereitstellung in Zeiten geringer Aktivität vermeidet.

Die Auswahl des geeigneten Durchsatzmodells hilft, Leistungsanforderungen effektiv mit der Kostenverwaltung in Einklang zu bringen.

Beste Praxis

  • Für vorhersehbare Workloads Durchsatz manuell bereitstellen.
  • Verwenden Sie die automatische Skalierung für unvorhersehbare oder sprunghafte Workloads.

Beispiel: Bereitstellung von Durchsatz mit Auto-Scale

C#

 

var throughputProperties = ThroughputProperties.CreateAutoscaleThroughput(maxThroughput: 4000);  // Autoscale up to 4000 RU/s 
var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
	Id = "autoscaleContainer",
	PartitionKeyPath = "/userId"
}, throughputProperties);

Beispiel: Manuelle Festlegung fester RU/s für stabile Workloads 

C#

 

var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
    Id = "manualThroughputContainer",
    PartitionKeyPath = "/departmentId"
}, throughput: 1000);  // Fixed 1000 RU/s

6. Nutzen Sie den Change Feed für effiziente Echtzeitverarbeitung

Der Änderungsfeed ermöglicht eine Echtzeit-, ereignisgesteuerte Verarbeitung, indem er automatisch Änderungen in der Datenbank erfasst und somit die Notwendigkeit von Abfragen eliminiert. Dies reduziert die Abfragekosten und steigert die Effizienz.

Best Practices

  • Verwenden Sie den Änderungsfeed für Szenarien, in denen Echtzeitdatenänderungen verarbeitet werden müssen (z. B. Echtzeitanalysen, Benachrichtigungen, Warnungen).

Beispiel: Lesen aus dem Änderungsfeed

C#

 

var iterator = container.GetChangeFeedIterator(
ChangeFeedStartFrom.Beginning(),
ChangeFeedMode.Incremental);
while (iterator.HasMoreResults)
{
    var changes = await iterator.ReadNextAsync();
    foreach (var change in changes)
    {
        Console.WriteLine($"Detected change: {change.Id}");
        // Verarbeiten Sie die Änderung (z. B. Ereignis auslösen, Cache aktualisieren)
    }
}

7. Nutzung der Lebensdauer (TTL) für automatische Datenablauf

Wenn Sie Daten haben, die nur für eine begrenzte Zeit relevant sind, wie z. B. Protokolle oder Sitzungsdaten, kann die Aktivierung der Lebensdauer (TTL) in Azure Cosmos DB helfen, die Speicherkosten zu verwalten. TTL löscht automatisch abgelaufene Daten nach dem festgelegten Aufbewahrungszeitraum, wodurch die Notwendigkeit einer manuellen Datenbereinigung entfällt. Dieser Ansatz reduziert nicht nur die Menge der gespeicherten Daten, sondern stellt auch sicher, dass Ihre Datenbank für Kosteneffizienz optimiert ist, indem veraltete oder unnötige Informationen entfernt werden.

Best Practices

  • Setzen Sie TTL für Container, in denen Daten automatisch ablaufen sollen, um die Speicherkosten zu senken.

Beispiel: Einstellung der Lebensdauer (TTL) für ablaufende Daten

C#

 

{
    "id": "sessionDataContainer",
    "partitionKey": { "paths": ["/sessionId"] },
    "defaultTtl": 3600  // 1 hour (3600 seconds)
}

In Cosmos DB, der maximale Time-to-Live (TTL)-Wert, der festgelegt werden kann, beträgt 365 Tage (1 Jahr). Das bedeutet, dass Daten automatisch gelöscht werden können, nachdem sie innerhalb eines Jahres nach Erstellung oder letzter Änderung ablaufen, je nachdem, wie Sie TTL konfigurieren.

8. Kreuzpartition-Abfragen vermeiden

Kreuzpartition-Abfragen können RU/s und Latenzzeiten erheblich erhöhen. Um dies zu vermeiden:

Beste Praxis

  • Schließen Sie immer den Partition-Schlüssel in Ihre Abfragen ein.
  • Gestalten Sie Ihre Partitionierungsstrategie so, dass der Zugriff über Partitionen minimiert wird.

Beispiel: Abfrage mit Partition-Schlüssel zur Vermeidung von Kreuzpartition-Abfragen

C#

 

var query = new QueryDefinition("SELECT * FROM Orders o WHERE o.customerId = @customerId")
    .WithParameter("@customerId", "12345"); 

var resultSetIterator = container.GetItemQueryIterator<Order>(query, requestOptions: new QueryRequestOptions
{
    PartitionKey = new PartitionKey("12345")
});

while (resultSetIterator.HasMoreResults)
{
    var response = await resultSetIterator.ReadNextAsync();
    foreach (var order in response)
    {
        Console.WriteLine($"Order ID: {order.Id}");
    }
}

Fazit

Diese Tipps sind während der Entwicklung sehr effektiv. Durch die Implementierung einer effektiven Partitionierungsstrategie, die Anpassung von Indexierungsrichtlinien, die Optimierung von Abfragen, die Anpassung der Konsistenzstufen und die Auswahl der geeigneten Durchsatzbereitstellungsmodelle können Sie die Leistung und Effizienz Ihrer Azure Cosmos DB-Bereitstellung erheblich verbessern. Diese Optimierungen verbessern nicht nur die Skalierbarkeit, sondern helfen auch, die Kosten zu verwalten, während sie ein Hochleistungsdatenbankerlebnis bieten.

Source:
https://dzone.com/articles/optimizing-performance-in-azure-cosmos-db