Menengah6 menit baca

Denormalisasi di DynamoDB

Datang dari SQL, denormalisasi terdengar seperti dosa — data terduplikasi, tidak ada single source of truth. Di DynamoDB itulah intinya. Tidak ada join, jadi Anda menyalin data terkait ke item yang membutuhkannya dan membacanya kembali dalam satu shot.

Apa itu denormalisasi di DynamoDB?

Denormalisasi di DynamoDB berarti menyalin data terkait ke item yang membacanya, sehingga satu query mengembalikan semuanya dalam satu shot. Karena DynamoDB tidak punya join, Anda pre-join saat write alih-alih menjahit tabel bersama saat baca. Trade-off-nya adalah staleness — hanya duplikasikan nilai yang jarang berubah.

  • Tanpa join berarti Anda pre-join saat write. Simpan nilai terkait pada item yang membacanya, agar query tidak pernah butuh lookup kedua.
  • Dua rasa. Embed data nested di atribut kompleks pada satu item, atau duplikasi nilai lintas banyak item.
  • Jebakannya adalah staleness. Saat sumber berubah, setiap salinan salah sampai Anda fan-out update. Hanya duplikasikan nilai yang jarang berubah.
  • Ia membeli baca, bukan tulis. Anda menukar write yang lebih banyak (dan lebih hati-hati) untuk baca murah single-request.

Mengapa tidak ada join untuk diandalkan

JOIN relasional menyusun ulang baris dinormalisasi saat baca. DynamoDB tidak punya join — Query membaca satu dan menyerahkan tepat apa yang tersimpan di sana. Tidak ada yang menjahit dua tabel untuk Anda. (Di jalur baca produksi, bagaimanapun — untuk audit ad-hoc atau cek drift, SQL Workbench DynoTable menjalankan JOIN sungguhan atas DynamoDB di sisi klien.)

Jadi data harus sudah dibentuk untuk baca. Jika layar butuh post dan nama authornya, nama itu harus hidup di suatu tempat yang sudah disentuh baca post. Paper Amazon Dynamo 2007 membuat trade ini eksplisit: jatuhkan fitur relasional untuk mendapat baca yang prediktabel pada skala — trade yang sekarang DynamoDB sampaikan sebagai baca single-digit-millisecond.

Pattern 1 — embed dengan atribut kompleks

Atribut DynamoDB bisa menampung map dan list nested, bukan hanya skalar. Jadi satu bentuk umum denormalisasi adalah menyumbat objek child langsung di dalam item parentnya alih-alih memberinya item sendiri.

Post dengan tag dan snapshot author kecil, semuanya di satu item:

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

Satu GetItem mengembalikan post, tag, dan blok author bersama. Tanpa baca kedua. Ini bagus untuk data yang dimiliki parent dan terbatas ukurannya — segenggam tag, satu snapshot author.

Satu item DynamoDB maksimal 400 KB, termasuk nama dan nilai atribut (Service Quotas). Embed list tanpa batas (setiap komentar pada post viral) dan Anda akan melampauinya.

Pattern 2 — duplikasi nilai lintas item

Kasus blog adalah yang textbook. Anda mendaftar post dan ingin tiap baris menampilkan display name author — tetapi tidak ingin baca kedua per post untuk mengambilnya.

Jadi Anda menulis nama author ke setiap item post saat post dibuat:

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

atas post (mis. GSI1PK = "POST", atau di-key by author) merender seluruh daftar — title dan author — tanpa lookup per-baris. begins_with pada partition key bukan hal; Query butuh equality partition key, jadi dengan partition key per-post daftar datang dari GSI, bukan Query atas POST#. Nama author didenormalisasi: salinan kanonis hidup di USER#12, dan setiap post membawa salinannya sendiri.

Trade-nya tepat di situ. Anda mengubah baca N+1 menjadi satu baca, dengan biaya memegang "Mara Vance" di N+1 tempat.

Embed vs. duplicate — mana

Embed (atribut kompleks)Duplicate (salin lintas item)
Bentukchild nested di dalam parentnilai sama pada banyak item
Terbaik untukdata terbatas milik parentnilai bersama yang banyak item tampilkan
Bacasatu GetItemsatu Query
Biaya updaterewrite satu item parentfan-out ke setiap salinan
Risiko ukuranlangit-langit item 400 KBtidak ada per item

Jangkau embed saat child hanya pernah muncul bersama parentnya. Jangkau duplicate saat banyak item independen perlu menampilkan nilai bersama yang sama.

Jebakan: salinan basi

Mara mengganti namanya menjadi "Mara V." Anda meng-update USER#12. Setiap item post masih bilang "Mara Vance" sampai Anda pergi memperbaikinya.

Jadi meng-update nilai yang diduplikasi adalah fan-out write, bukan one-liner. Anda Query setiap item terdampak dan rewrite masing-masing — idealnya dijaga agar hanya menyentuh baris yang masih memegang nilai lama:

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

Anda bisa menyusun SET kondisional itu terhadap authorName di Expression Builder dan menyalin UpdateExpression serta ConditionExpression yang dihasilkan langsung ke kode.

Fan-out adalah satu write per item. Query GSI ber-key author untuk post author itu, lalu keluarkan update. Urutannya:

"DynamoDB"App"DynamoDB"App"Update nama USER"Query post author""POST"Update tiap authorName"

Setiap perubahan ke sumber adalah query plus write per salinan. Di DynoTable fan-out mendarat di staging area dulu, sebagai diff per-atribut yang bisa ditinjau per item — Anda melihat setiap salinan yang akan berubah sebelum apa pun di-ship.

Inilah mengapa aturannya hanya duplikasikan nilai yang jarang berubah. Display name, plan tier, label kategori — baik. Counter live atau field yang sering diedit — jangan; fan-out akan memakan Anda hidup-hidup.

Biaya fan-out write

Setiap salinan yang Anda update adalah write terpisah yang ditagih. Di us-east-1 on-demand, meng-update 50 item post setelah rename author menelan 50 × WCU — biasanya 1 WCU per KB per item saat tiap baris post ≤ 1 KB. Sisi baca tetap satu Query; sisi tulis berskala dengan berapa banyak duplikat yang Anda pelihara. Perkirakan kedua jalur di kalkulator harga.

Kapan normalisasi tetap menang

Jika nilai sering berubah, atau satu item dibaca by pattern yang benar-benar tidak prediktabel, jaga dinormalisasi dan terima baca ekstra. Denormalisasi adalah optimasi untuk access pattern yang diketahui, read-heavy — bukan default untuk diterapkan di mana-mana. Pre-join baca yang benar-benar Anda jalankan, dan biarkan sisanya.

Untuk memutuskan di mana atribut yang diduplikasi ini hidup, model access pattern dulu — lihat single-table design dan, untuk sisi baca dari trade, Query vs Scan.

Unduh DynoTable untuk memeriksa tabel yang didenormalisasi, melihat salinan mana yang drift, dan menjalankan fan-out update terhadap data Anda sendiri. SQL Workbench-nya bahkan bisa JOIN sumber kebenaran terhadap salinan untuk menemukan drift dalam satu query.

Diperbarui