DynamoDB'de Type Attribute
SQL'de bir satırın tablosu onun tipidir — documents içindeki bir satır bir
belgedir. DynamoDB tek tablosu her entity'yi tek bir şema altında karıştırır,
dolayısıyla bir item "bu nedir?" sorusuna yerleşik bir cevap taşımaz.
Type attribute'ı o cevabı geri koyar: her item üzerinde, temsil ettiği entity'yi adlandıran düz bir string.
DynamoDB'de Type attribute nedir?
Type attribute, her item'a damgaladığınız düz bir string'dir — örneğin EntityType: "Document" — temsil ettiği entity'yi adlandırır. Bir tek tablo, pek çok entity'yi tek bir şema altında karıştırdığından item'lar yerleşik bir tipe sahip değildir. Type bunu geri koyar; böylece kodunuz satırları tanımlar, bir GSI'yi tek bir entity'ye daraltır ve taşımalardan sağ çıkar.
- Her yazmada bir Type damgala. Her item üzerinde tek bir attribute —
EntityType: "Document"— istisnasız. Birkaç bayta mal olur ve sonradan seni kurtarır. - Karışık bir partition içinde entity'leri tanımlar. Bir
Queryworkspace'leri, belgeleri ve yorumları bir arada döndürür; key prefix'lerini ayrıştırmadan hangisinin hangisi olduğunu Type kodun için söyler. - Bir GSI üzerinde tek entity filtrelemeyi besler. Type'ı bir index'e project et, böylece aşırı yüklü bir index'i tam olarak tek bir entity tipine daraltabilirsin.
- Taşımalar için kaçış kapındır. Yeniden modellemek için export ettiğinde ya da bir entity'yi kendi tablosuna taşıdığında, Type üzerinden böldüğün sütundur.
Karışık bir tablo tipi neden kaybeder
Single-table design her entity'yi PK ve SK gibi
genel key'lerin arkasında tek bir tabloda saklar. Bütün mesele bu — tek bir Query
bir ebeveyni ve çocuklarını bir arada döndürür. Ama bu, bir partition'ın heterojen
olduğu anlamına gelir.
Bir SaaS belge-iş birliği uygulamasını ele al. Bir workspace partition'ı workspace kaydını, belgelerini ve o belgelerdeki yorumları tutar:
| PK | SK | attributes |
|---|---|---|
| WS#acme | META | name, plan, seats |
| WS#acme | DOC#a1#META | title, owner, wordCount |
| WS#acme | DOC#a1#CMT#0007 | author, body, createdAt |
| WS#acme | DOC#a1#CMT#0008 | author, body, createdAt |
Query PK = "WS#acme" dört item'ın tümünü tek bir faturalanan okumada geri verir.
Şimdi kodun elinde ham item'ların bir listesi var ve hangisinin belge hangisinin
yorum olduğunu söyleyecek güvenilir bir yolu yok — SK'yı string olarak
eşleştirmek dışında, ki bu da key formatın değiştiği an kırılgan hale gelir.
Her item'a Type'ı damgala
Çözüm, her yazmada entity'yi adlandıran tek bir attribute:
| PK | SK | EntityType | title |
|---|---|---|---|
| WS#acme | META | Workspace | — |
| WS#acme | DOC#a1#META | Document | Q3 Roadmap |
| WS#acme | DOC#a1#CMT#0007 | Comment | — |
item.EntityType === "Document" üzerinden dallanmak kararlı bir eşitlik
kontrolüdür. SK.startsWith("DOC#") && SK.includes("#CMT#") ayrıştırmak ise
key'ini revize ettiğin an kırılan bir tahmindir. Type, okuma mantığını key
kodlamandan ayırır — asıl kazanç budur.
Tek bir okuma üç entity tipi döndürür; Type attribute'ı key'lere dokunmadan her item'ı doğru işleyiciye yönlendirir.
Bir GSI'yi tek bir entity'ye daralt
Type, index'lerde hak ettiğini kazanır. Diyelim ki "bu workspace'te son zamanlarda
değişen her şeyi, en yenisi önce" listelemek için GSI1PK = WS#acme,
GSI1SK = updatedAt üzerinde key'lenmiş bir GSI ekledin. Aşırı yüklü bir index
belgeleri ve yorumları içeri süpürür — ama bir akış arayüzü yalnızca belgeleri
isteyebilir.
Onu daraltmanın iki yolu var ve aradaki fark paradır:
| Yaklaşım | Maliyeti | Ne zaman kullanılır |
|---|---|---|
Type üzerinde FilterExpression | Eşleşen tüm item'ları okur, hepsi için faturalandırır, eşleşmeyenleri okumadan sonra atar | Sonuçta karışık entity'ler nadir; hızlıca yola çıkmak için |
Sparse index (GSI1PK'da Type) | Yalnızca istediğin entity index'e iner | Tek bir entity baskınsa; sıfır israf istiyorsan |
Bir FilterExpression item'lar okunduktan sonra ve kapasite tüketildikten
sonra çalışır — AWS, filtrelemenin okuma maliyetini düşürmediğini açıkça
belirtir
(DynamoDB Developer Guide: FilterExpression).
Type üzerinde filtreleme dürüsttür, bedava değil: attığın yorumlar için ödersin.
Akışı belgelere daraltmak için, sorgu Type attribute'ı üzerinde bir koşul taşır.
FilterExpression'ı, name'leri ve value'ları
DynamoDB expression builder ile birleştir —
ayrılmış bir kelimeyi yanlış yazmaman için #t = :doc placeholder'ını üretir.
KeyConditionExpression GSI1PK = :ws
FilterExpression #t = :doc
ExpressionAttributeNames { "#t": "EntityType" }
ExpressionAttributeValues { ":ws": "WS#acme", ":doc": "Document" }
Index'in yalnızca belgeleri taşımasını ve filtreyi tamamen atlamasını mı
istiyorsun? GSI1PK'yı yalnızca belge item'larına yaz — bir sparse index.
GSI key'i olmayan item'lar asla index'e kopyalanmaz, dolayısıyla okuma yalnızca
belgelere dokunur. Hangi item'ların uygun olduğunu yazara söyleyen şey Type
attribute'ıdır.
Değeri kararlı ve tekil tut
Değeri bir kez seç ve onu bir enum gibi ele al. Document, asla bazen Doc bazen
document değil — kayan bir değer, hiç değerin olmamasından daha kötüdür, çünkü
eşitlik kontrollerin bir büyük/küçük harf yazımında geçer ve sessizce diğerini
kaçırır.
Item başına tek Type. Bir item iki entity gibi hissettiriyorsa, bu genellikle bir modelleme kokusudur — tek bir satır iki şapka takmak yerine, her biri kendi koleksiyonunda ya da sort-key aralığında iki item olmalı.
Taşıma getirisi
Type'ı ihtiyacın olmadan önce damgalamanın nedeni: yeniden modelleme. Önerilen yeniden modelleme yolu export, dönüştür, yeniden import et — ve AWS tam da bu tür çevrimdışı yeniden şekillendirme için S3'e toplu export'u belgeler (DynamoDB'yi S3'e export etme).
O gün geldiğinde, Type GROUP BY yaptığın sütundur. Yorumları kendi tablolarına
mı kaldırmak istiyorsun, yoksa export'u bir analitik warehouse için entity başına
dosyalara mı yeniden normalleştirmek? Dökümü EntityType üzerinden bölersin. O
olmadan, milyonlarca satır boyunca key'leri tersine mühendislik yapmaya geri
dönersin.
Sonraki adımlar
Type attribute'ı ucuz bir sigortadır: karışık bir okumada entity'leri tanımla, aşırı yüklü bir GSI'yi filtrele ve yeniden modellediğinde temizce böl. İlk günden her yazmaya damgala — onu canlı bir tabloya sonradan eklemek tam bir geri doldurma demektir.
İlgili okumalar: bu attribute'ın hizmet ettiği karışık-partition deseni için
single-table design, bir sparse index'in arkasındaki
index şeklini seçmek için GSI vs LSI, ve bir
FilterExpression'ın neden asla okuma maliyetinden kurtarmadığı için
Query vs Scan.
Type üzerindeki filtreyi DynamoDB expression builder ile oluştur, ve gerçek bir karışık-entity tablosuna göz atıp Type sütununun her item boyunca hizalandığını görmek için DynoTable'ı dene.