DynamoDB'de Key Overloading
SQL'den geliyorsanız bir sütun sonsuza dek tek bir şey ifade eder: orders.created_at
her zaman bir tarihtir, users.email her zaman bir e-postadır. Key overloading bunu
bir kenara atar. Partition ve anahtarlarına genel adlar verirsiniz — pk, sk — ve
her item tipinin bunlara farklı bir anlam yüklemesine izin verirsiniz. Tek tablo, birçok
varlık, tek bir şekil.
DynamoDB'de key overloading nedir?
Key overloading, birçok varlık tipini tek bir tabloda pk/sk gibi genel anahtar adları altında saklamak, tipi değerde kodlamaktır (USER#u_3001, INVOICE#2026-0014). Attribute adı nötr kalır, böylece senlar, faturalar ve olaylar tek bir partition'ı paylaşır; değer tipi taşır ve bir sort-key öneki, tek bir Query'nin her varlığı begins_with ile dilimlemesine olanak tanır.
- Genel anahtar adları, tipli değerler. Anahtarlarınızı
pk/skolarak adlandırın ve varlık tipini değere koyun:pk = "TENANT#acme",sk = "USER#u_3001". Ad aptaldır; tipi değer taşır. - Single-table tasarımını mümkün kılan şey budur. Overloading olmadan paylaşılan bir tablo
yalnızca bir çöp çekmecesidir. Onunla birlikte her varlık,
Queryçekebileceğiniz bir partition'da oturur. - Ödül
begins_with'tir. Sort key üzerindeki bir tip öneki, tek birQuery'nin bir varlığın tamamını veya bir diliminiScanolmadan ve filtre olmadan çekmesini sağlar. - Bedeli: okunabilirlik. Ham bir
pk/skdökümü sana hiçbir şey söylemez. Önekleri çözen bir görüntüleyiciye ihtiyacınız var, aksi halde string'lere gözlerinizi kısarak bakarsınız.
Neden genel adlar gerçek adları yener
DynamoDB tablo başına en fazla iki anahtar attribute'u verir ve bir Query yalnızca tek bir
partition key'i hedefleyebilir. Yani anahtarınızı userId olarak adlandırırsanız, o tabloda
temiz bir şekilde yalnızca kullanıcı item'ları yaşayabilir — geri kalan her şey ya sahte bir
userId uydurmak ya da kendi tablosuna taşınmak zorunda kalır.
Overloading bunu aşar. pk gibi nötr bir ad hiçbir varlığa bağlanmaz, böylece bir kullanıcı,
bir fatura ve bir denetim olayı aynı anahtar attribute'unu ve aynı tabloyu paylaşabilir.
Item'ın ne olduğunu attribute adı değil, değer söyler.
Bu, single-table tasarımını teoriden gerçekten sorgulayabileceğiniz bir şeye dönüştüren hamledir. Paylaşılan tablo kaptır; overloading ise farklı varlıkların onun içinde bir arada var olmasını sağlayan şeydir.
Çok kiracılı bir örnek
Diyelim ki bir SaaS faturalandırma ürünü işletiyorsunuz. Her kiracının üyeleri, faturaları ve bir denetim izi vardır. Üç tablo yerine hepsini bir tabloya koyun ve anahtarları overload edin:
| pk | sk | attributes |
|---|---|---|
| TENANT#acme | META | name="Acme Inc", plan="team" |
| TENANT#acme | USER#u_3001 | email, role="admin" |
| TENANT#acme | USER#u_3002 | email, role="member" |
| TENANT#acme | INVOICE#2026-0014 | amount_cents, status="paid" |
| TENANT#acme | INVOICE#2026-0015 | amount_cents, status="open" |
| TENANT#acme | EVENT#2026-06-23T09:12Z | actor="u_3001", action="invite" |
Her satır pk = "TENANT#acme" değerini paylaşır, böylece tek bir oluştururlar — hepsi
bir arada bulunur, hepsine tek bir partition okumasıyla erişilebilir.
Asıl işi sort-key öneki yapıyor. Varlıkları hem gruplar hem de sıralar.
Overload edilmiş koleksiyonu sorgulayın
Tip sort-key önekinde yaşadığı için, begins_with partition'ı hiçbir şeyi taramadan
varlığa göre dilimler:
Query pk = "TENANT#acme" -- the entire tenant, every type
Query pk = "TENANT#acme" AND begins_with(sk, "USER#") -- just members
Query pk = "TENANT#acme" AND begins_with(sk, "INVOICE#") -- just invoices
Yalnızca koşulun eşleştiği item'lar için ödeme yaparsınız, partition'ın tamamı için değil —
sonra çöpe attığınız satırları okumak için ödeme yaptığınız filtrelenmiş bir
Scan işleminin tam tersi. AWS buna anahtar koşulu (condition) der;
partition'dan herhangi bir veri çıkmadan önce anahtarlar üzerinde çalışır.
O begins_with koşulunu elle oluşturursanız, tip etiketlerini doğru yazın — USER# yerine
sapık bir USERS# sessizce hiçbir şey döndürür. İfade oluşturucu,
önekler gerçekten yazdığınızla eşleşsin diye KeyConditionExpression ve
ExpressionAttributeValues haritasını üretir.
Index'i de overload edin
Aynı numara bir için de geçerlidir. Ona genel anahtar adları verin — gsi1pk, gsi1sk —
ve her varlığın ihtiyaç duyduğu şeyi yazmasına izin verin. Bir index böylece temel tablonun
karşılayamayacağı modelleri yanıtlar.
| pk | sk | gsi1pk | gsi1sk |
|---|---|---|---|
| TENANT#acme | INVOICE#2026-0015 | STATUS#open | 2026-06-30 |
| TENANT#acme | INVOICE#2026-0014 | STATUS#paid | 2026-06-12 |
| TENANT#beta | INVOICE#2026-0099 | STATUS#open | 2026-06-25 |
Artık Query gsi1 WHERE gsi1pk = "STATUS#open", tüm kiracılar genelinde her açık faturayı
son ödeme tarihine göre sıralı olarak listeler — temel tablonun kiracı kapsamlı anahtarlarının
asla karşılayamayacağı, partition'lar arası bir görünüm. Farklı bir varlık gsi1'i kendi
anlamıyla yeniden kullanabilir (örneğin gsi1pk = "ROLE#admin"), böylece tek bir index birkaç
okumayı kapsar. Sadece bir GSI'nin nihai tutarlı olduğunu unutmayın —
yazmaları temel tablonun gerisinde kalır.
Bunu DynoTable'da yapın
Ham overload edilmiş anahtarlar okumaya düşmandır: INVOICE#2026-0015 ve
EVENT#2026-06-23T09:12Z düz bir listede birbirine karışır. Partition'a göre gruplayan ve
önekleri öne çıkaran bir görüntüleyici, çöp çekmecesini yeniden varlıklara dönüştürür.

Tuzaklar
- Ayıraçları bir kez seçin ve asla değiştirmeyin.
#yerleşik gelenektir. Varlıklar arasında#ile:karıştırmak, hiçbir şeyin sizi uyarmadığı biçimlerdebegins_with'i bozar. - Aralık matematiği gerektiren değerleri overload etmeyin.
INVOICE#2026-0015şeklindeki bir sort key sözlüksel olarak sıralanır, sayısal olarak değil — string sıralaması kastettiğiniz sırayla eşleşsin diye id'leri ve ISO-8601 tarihlerini kullanın. - Önek ad alanını ayırın. İkisi de
USERile başlayan iki varlık tipi (örneğinUSER#veUSERGROUP#)begins_with(sk, "USER")altında çakışır. Önekleri ilk karakterden itibaren belirsizlikten uzak tutun. - Anahtarlardan önce okumayı planlayın. Overloading, sıraladığınız erişim modellerine hizmet eder. Okumalarınızı henüz bilmiyorsanız, önce single-table tasarımına bakın — anahtarlar sorguların akışında sonraki adımdır.
Bir partition'ın haritasını çıkarın, ardından kendi overload edilmiş anahtarlarınıza göz atmak
ve tek bir Query'nin bir kiracının tamamını bir kerede geri getirişini izlemek için
DynoTable'ı indirin.
Overload edilmiş bir partition'da sorgu maliyeti
TENANT#acme altındaki her üyeyi begins_with(sk, "USER#") ile listelemek yalnızca
kullanıcı satırlarını okur — fatura ya da olayları değil — çünkü anahtar koşulu, veri
partition'dan çıkmadan önce filtreler. 200 kullanıcısı (her biri 2 KB) ve 5.000 denetim
olayı (her biri 1 KB) olan bir kiracıda bu sorgu ~400 KB'a dokunur (~100 nihai tutarlı
RCU). Kullanıcıları bulmak için tablonun tamamında bir Scan, her kiracıdaki her öğeyi
ölçümlerdi.
Temsili overload edilmiş öğeleri öğe boyutu hesaplayıcısına yapıştırın, sonra liste sorgularını fiyatlandırma hesaplayıcısında tahmin edin.
Tek tablo aracıyla tasarlayın
Varlıkları (Tenant, User, Invoice, Event) ve erişim desenlerini ("bir kiracının
kullanıcılarını listele", "kiracılar arası açık faturalar")
tek tablo tasarımı aracına girin. Araç,
production'da kullanacağınız overload öneklerine uyan pk/sk şablonları ve GSI
anahtarları önerir — siz CloudFormation'a bağlanmadan önce.
Desenlerden sorgu üretin
Önekler sabitlendikten sonra anahtar koşullarını
ifade oluşturucuda kurun ve
sorgu oluşturucudan sayfalamalı bir program dışa
aktarın. Önek yazım hataları (USER# yerine USERS#) hata vermeden boş küme
döndürür — üretilmiş ifadeler bu sessiz hata biçimini azaltır.
Varlık tipi önek kaydı
Geliştiricilerin başvurabileceği kısa bir iç tablo tutun:
| Varlık | Sort öneki | Örnek SK | Sorgu dilimi |
|---|---|---|---|
| Kiracı meta | META | META | Tek öğelik get |
| Kullanıcı | USER# | USER#u_3001 | begins_with(sk, "USER#") |
| Fatura | INVOICE# | INVOICE#2026-0015 | begins_with(sk, "INVOICE#") |
| Olay | EVENT# | EVENT#2026-06-23T09:12Z | azalan okumayla zaman sıralı kuyruk |
Yeni varlık tipleri, mevcut öneklerin begins_with'i altında çakışmayan önekler
seçmelidir — dikkatle uzatmadığınız ya da ayıraçla ayırmadığınız sürece USER# ve
USERGROUP# ikisi de begins_with(sk, "USER") ile eşleşir.


