Azure Cosmos DB Bölümleme: Partition Key Seçimi ve Stratejiler
# Azure Cosmos DB Bölümleme: Partition Key Seçimi ve Stratejiler
CosmosDB'de performans ve ölçeklenebilirlik, partition key seçimine doğrudan bağlıdır. Yanlış bir seçim sıcak bölümler (hot partitions) yaratır, bu da hız düşüşü ve maliyet artışı demektir. Doğru stratejiye karar vermek üç soruya cevap vermekle başlar: Verileriniz nasıl büyüyor? Sorgularınız hangi alanlara odaklanıyor? Yazma işlemleri eşit dağılıyor mu?
Partition key, Cosmos DB'nin belgelerinizi fiziksel bölümlere dağıtmak için kullandığı alandır. Her belge, bu alanın değerine göre bir bölüme atanır. Örneğin `/userId` seçerseniz, tüm kullanıcı verileri kullanıcı kimliğine göre gruplandırılır.
1. Yüksek Kardinaliteli Alanlar (Tercih Edilen)
Birçok farklı değere sahip alanlar en iyi seçimdir. `/userId`, `/orderId`, `/email` gibi alanlar veriyi eşit dağıtır.
2. Sıcak Bölüm Riski
`/country` gibi düşük kardinaliteli alanlar sorun yaratabilir. Türkiye'den çok fazla istek gelirse, o bölüm aşırı yüklenir.
3. Sorgu Desenleri
Sık sık `WHERE userId =?` sorgusu yapıyorsanız `/userId` doğru seçimdir. Böyle sorgular tek bölümde çalışır (partition-scoped query), çok hızlıdır.
Bir e-ticaret uygulamasında siparişler tablosunu düşünelim. İki seçenek vardır:
Seçenek 1: Yanlış Seçim (/status)
1{2"id": "order-123",3"status": "pending",4"userId": "user-456",5"amount": 1506}Eğer partition key `/status` olursa, tüm "pending" siparişler bir bölüme gider. Yoğun saatlerde bu bölüm tıkanır.
Seçenek 2: Doğru Seçim (/userId)
1{2"id": "order-123",3"userId": "user-456",4"status": "pending",5"amount": 1506}Partition key `/userId` ile her kullanıcının siparişleri ayrı bölümlere dağılır. Yazma ve okuma işlemleri paralel çalışır.
1const containerDefinition = {2id: "orders",3partitionKey: {4paths: ["/userId"],5kind: "Hash"6}7};89await database.containers.create(containerDefinition);Bölüm anahtarını sorguda kullanırsan çok hızlı sonuç alırsın:
1const query = "SELECT * FROM c WHERE c.userId = @userId";2const result = await container.items.query(3{ query, parameters: [{ name: "@userId", value: "user-456" }] }4).fetchAll();5// Çıktı: 1 bölümde arama, ~10-50msEğer bölüm anahtarını kullanmazsan, tüm bölümleri tara (cross-partition query):
1const query = "SELECT * FROM c WHERE c.status = @status";2const result = await container.items.query(3{ query, parameters: [{ name: "@status", value: "pending" }] }4).fetchAll();5// Çıktı: Tüm bölümler taranır, ~500-2000ms, daha pahalıPartition key seçerken yüksek kardinaliteli, sık sorgulanan ve yazma işlemlerini eşit dağıtan alanları tercih et. Düşük kardinaliteli alanlar sıcak bölüm sorunu yaratır. Doğru seçim yapıldığında, aynı RU bütçesiyle 10-100 kat daha fazla işlem yapabilirsin.
0 yorum