Orta6 dakikalık okuma

DynamoDB'de Denormalizasyon

SQL'den geliyorsan denormalizasyon bir günah gibi gelir — çoğaltılmış veri, tek bir doğruluk kaynağı yok. DynamoDB'de tüm mesele budur. Join yoktur, bu yüzden ilgili veriyi ona ihtiyaç duyan öğenin üzerine kopyalar ve tek seferde geri okursun.

DynamoDB'de denormalizasyon nedir?

DynamoDB'de denormalizasyon, ilgili veriyi onu okuyan öğenin üzerine kopyalamak demektir; böylece tek bir sorgu her şeyi bir seferde döner. DynamoDB'de join olmadığı için okuma zamanında tabloları dikmek yerine yazma zamanında önceden join edersin. Takas bayatlamadır — yalnızca nadiren değişen değerleri çoğalt.

  • Join yok demek yazma zamanında önceden join demektir. İlgili değeri onu okuyan öğede sakla ki sorgu asla ikinci bir lookup istemesin.
  • İki çeşidi var. İç içe veriyi bir öğede karmaşık bir attribute içine göm, veya bir değeri birçok öğe boyunca çoğalt.
  • Tuzak bayatlamadır. Kaynak değişince her kopya, güncellemeyi yayana kadar yanlıştır. Yalnızca nadiren değişen değerleri çoğalt.
  • Okuma alır, yazma değil. Ucuz, tek istekli okumalar için daha fazla (ve daha dikkatli) yazma takas edersin.

Neden düşülecek join yoktur

İlişkisel bir JOIN okuma zamanında normalize satırları yeniden birleştirir. DynamoDB'de join yoktur — bir Query bir okur ve orada saklananı aynen verir. İki tabloyu senin için diken bir şey yoktur. (En azından production okuma yolunda — ad-hoc audit veya drift kontrolü için DynoTable'ın SQL Workbench'i DynamoDB üzerinde istemci tarafında gerçek bir JOIN çalıştırır.)

Yani veri zaten okuma için şekillendirilmiş olmalıdır. Bir ekran bir post ve yazarının adını istiyorsa, o ad post okumasının zaten dokunduğu bir yerde yaşamalıdır. 2007 Amazon Dynamo makalesi bu takası açık yaptı: ölçekte öngörülebilir okumalar için ilişkisel özellikleri düş — DynamoDB'nin şimdi tek haneli milisaniye okumalar olarak sunduğu takas.

Desen 1 — karmaşık attribute ile göm

DynamoDB attribute'ları yalnızca skaler değil, iç içe map ve list tutabilir. Yani denormalizasyonun yaygın bir biçimi, çocuğa kendi öğesini vermek yerine doğrudan parent öğesinin içine tıkmaktır.

Etiketleri ve küçük bir yazar anlık görüntüsüyle bir post, hepsi bir öğede:

PKSKauthortags
POST#9f3META{id: U#12, name: "Mara Vance"}["dynamodb","aws"]

Tek bir GetItem postu, etiketleri ve yazar bloğunu birlikte döner. İkinci okuma yok. Bu, parent'a ait ve boyutu sınırlı veri için harikadır — bir avuç etiket, bir yazar anlık görüntüsü.

Tek bir DynamoDB öğesi, attribute adları ve değerleri dahil 400 KB'ta tıkanır (Service Quotas). Sınırsız bir liste göm (viral bir posttaki her yorum) ve onu aşarsın.

Desen 2 — bir değeri öğeler boyunca çoğalt

Blog vakası ders kitabıdır. Postları listelersin ve her satırın yazarın görünen adını göstermesini istersin — ama onu getirmek için post başına ikinci bir okuma istemezsin.

Bu yüzden post oluşturulurken yazarın adını her post öğesine yazarsın:

PKSKauthorIdauthorNametitle
POST#9f3METAU#12"Mara Vance""Modeling 1:N"
POST#a71METAU#12"Mara Vance""Sparse GSIs"
POST#b04METAU#88"Lio Tan""Query vs Scan"

Postlar üzerinde bir (diyelim GSI1PK = "POST", veya yazara göre anahtarlı) tüm listeyi — başlık ve yazar — satır başına lookup olmadan render eder. Partition key üzerinde begins_with bir şey değildir; bir Query partition-key eşitliği ister, bu yüzden post başına partition key'lerle liste POST# üzerinde bir Query'den değil GSI'den gelir. Yazar adı denormalized'dır: kanonik kopya USER#12'de yaşar ve her post kendi kopyasını taşır.

Takas tam oradadır. N+1 okumayı bir okumaya çevirdin, "Mara Vance"'i N+1 yerde tutma pahasına.

Göm vs çoğalt — hangisi

Göm (karmaşık attribute)Çoğalt (öğeler boyunca kopya)
Şekilçocuk parent içinde iç içeaynı değer birçok öğede
En iyisisınırlı, parent'a ait veribirçok öğenin gösterdiği paylaşılan değer
Okumabir GetItembir Query
Güncellemetek parent öğeyi yeniden yazher kopyaya yayıl
Boyut riski400 KB öğe tavanıöğe başına yok

Çocuk yalnızca parent'ıyla birlikte görünüyorsa göm'e uzan. Birçok bağımsız öğe aynı paylaşılan değeri göstermek zorundaysa çoğalt'a uzan.

Tuzak: bayat kopyalar

Mara kendini "Mara V." olarak yeniden adlandırır. USER#12'yi güncellersin. Her post öğesi sen düzeltine kadar hâlâ "Mara Vance" der.

Yani çoğaltılmış bir değeri güncellemek tek satır değil, bir fan-out yazmasıdır. Etkilenen her öğeyi sorgular ve her birini yeniden yazarsın — idealde hâlâ eski değeri tutan satırlara yalnızca dokunacak şekilde korunmuş:

UPDATE POST#9f3
SET authorName = "Mara V."
WHERE authorName = "Mara Vance"

authorName'e karşı o koşullu SET'i Expression Builder'da oluşturup üretilen UpdateExpression ve ConditionExpression'ı doğrudan koduna kopyalayabilirsin.

Fan-out öğe başına bir yazmadır. O yazarın postları için yazar-anahtarlı GSI'yi sorgula, sonra güncellemeleri yolla. Sıra:

"DynamoDB"App"DynamoDB"App"USER"Yazarın postlarını Query et""POST"Her authorName'i güncelle"

Kaynağa her değişiklik, kopya başına bir sorgu artı bir yazmadır. DynoTable'da fan-out önce staging area'ya düşer — öğe başına incelenebilir attribute diff olarak — bir şey gitmeden önce değişecek her kopyayı görürsün.

Bu yüzden kural yalnızca nadiren değişen değerleri çoğalttır. Bir görünen ad, bir plan tier'ı, bir kategori etiketi — tamam. Canlı bir sayaç veya sık düzenlenen bir alan — yapma; fan-out seni yer bitirir.

Fan-out yazma maliyeti

Güncellediğin her kopya ayrı faturalanan bir yazmadır. us-east-1 on-demand'de bir yazar yeniden adlandırmasından sonra 50 post öğesini güncellemek 50 × WCU tutar — her post satırı ≤ 1 KB iken tipik olarak öğe başına 1 KB başına 1 WCU. Okuma tarafı bir Query kalır; yazma tarafı tuttuğun kopya sayısıyla ölçeklenir. Her iki yolu da pricing calculator'da tahmin et.

Normalizasyonun hâlâ kazandığı yer

Bir değer sık değişiyorsa veya bir öğe gerçekten öngörülemez desenler tarafından okunuyorsa, normalize tut ve ekstra okumayı kabul et. Denormalizasyon bilinen, okuma-ağır erişim desenleri için bir optimizasyondur — her yere uygulanacak bir varsayılan değil. Gerçekten çalıştırdığın okumaları önceden join et, gerisini bırak.

Bu çoğaltılmış attribute'ların nerede yaşayacağına karar vermek için önce erişim desenlerini modelle — bak single-table design ve takasın okuma tarafı için Query vs Scan.

Denormalize bir tabloyu incelemek, hangi kopyaların saptığını bulmak ve fan-out güncellemesini kendi verine karşı çalıştırmak için DynoTable'ı indir. SQL Workbench'i hatta drift'i tek sorguda bulmak için doğruluk kaynağını kopyalara karşı JOIN edebilir.

Güncellendi