Lanjutan7 menit baca

Kelebihan Kunci di DynamoDB

Berasal dari SQL, kolom berarti satu hal selamanya: orders.created_at selalu a tanggal, users.email selalu berupa email. Kelebihan beban kunci menghilangkan hal tersebut. kamu berikan nama umum partisi dan pk, sk — dan biarkan setiap item diketik menuangkan makna berbeda ke dalamnya. Satu tabel, banyak entitas, satu bentuk.

Apa yang dimaksud dengan kelebihan kunci di DynamoDB?

Kelebihan kunci adalah menyimpan banyak tipe entitas dalam satu tabel dengan nama kunci umum seperti pk/sk, mengkodekan tipe dalam nilai (USER#u_3001, INVOICE#2026-0014). Nama atribut tetap netral sehingga pengguna, faktur, dan peristiwa berbagi satu partisi; nilainya membawa tipe, dan awalan kunci pengurutan memungkinkan satu Query mengiris setiap entitas melalui begins_with.

  • Nama kunci umum, nilai yang diketik. Beri nama kunci Anda pk/sk dan masukkan entitasnya ketik nilainya: pk = "TENANT#acme", sk = "USER#u_3001". Namanya bodoh; nilainya membawa tipe.
  • Inilah yang membuat desain tabel tunggal berhasil. Tanpa membebani secara berlebihan, tabel bersama hanyalah laci sampah. Dengan itu, setiap entitas berada di partisi yang Anda dapat Query.
  • begins_with adalah hasilnya. Awalan tipe pada kunci pengurutan memungkinkan satu Query tarik seluruh entitas, atau satu bagiannya, tanpa Scan dan tanpa filter.
  • Biaya: keterbacaan. Dump pk/sk mentah tidak memberi tahu Anda apa pun. Anda membutuhkan sebuah penampil yang menerjemahkan awalan, atau Anda akan menyipitkan mata pada string.

Mengapa nama generik mengalahkan nama asli

DynamoDB memberi Anda paling banyak dua atribut utama per tabel, dan Query hanya dapat menargetkan a kunci partisi tunggal. Jadi jika Anda memberi nama kunci Anda userId, hanya item pengguna yang dapat tinggal di dalamnya tabel itu dengan rapi — yang lainnya harus memalsukan userId atau pindah ke tabelnya sendiri.

Kelebihan beban menghindari hal itu. Nama netral seperti pk tidak berkomitmen pada entitas mana pun, jadi pengguna, faktur, dan peristiwa audit semuanya dapat berbagi atribut kunci yang sama dan meja yang sama. Nilai, bukan nama atribut, yang menentukan item tersebut.

Ini adalah langkah yang mengubah desain meja tunggal dari teori menjadi sesuatu yang sebenarnya dapat Anda tanyakan. Tabel bersama adalah wadahnya; kelebihan beban inilah yang memungkinkan entitas berbeda hidup berdampingan di dalamnya.

Contoh multi-penyewa

Katakanlah Anda menjalankan produk penagihan SaaS. Setiap penyewa memiliki anggota, faktur, dan audit jejak. Alih-alih tiga tabel, letakkan semuanya dalam satu dan muat ulang kuncinya:

pkskattributes
TENANT#acmeMETAname="Acme Inc", plan="team"
TENANT#acmeUSER#u_3001email, role="admin"
TENANT#acmeUSER#u_3002email, role="member"
TENANT#acmeINVOICE#2026-0014amount_cents, status="paid"
TENANT#acmeINVOICE#2026-0015amount_cents, status="open"
TENANT#acmeEVENT#2026-06-23T09:12Zactor="u_3001", action="invite"

Setiap baris berbagi pk = "TENANT#acme", sehingga membentuk satu — semuanya terletak di lokasi yang sama, semua dapat dijangkau dalam satu partisi baca.

Partisi: TENANT#acmesk: METAsk: PENGGUNA#u_3001sk: INVOICE#2026-0015sk: ACARA#23-06-2026T09:12ZSatu Pertanyaan

Awalan tombol sortir melakukan pekerjaan sebenarnya. Ini mengelompokkan entitas dan mengurutkannya.

Kueri koleksi yang kelebihan beban

Karena tipenya berada di awalan tombol sortir, begins_with membagi partisi berdasarkan entitas tanpa memindai apa pun:

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

Anda hanya membayar untuk item yang kondisinya cocok, bukan seluruh partisi — the kebalikan dari Scan yang difilter, di mana Anda membayar untuk membaca baris kamu kemudian membuangnya. AWS menyebutnya sebagai kunci kondisi; itu berjalan pada tombol sebelumnya data apa pun meninggalkan partisi.

Jika Anda membuat kondisi begins_with itu dengan tangan, buatlah tag tipe dengan benar - nyasar USERS# alih-alih USER# tidak menghasilkan apa pun, secara diam-diam. Itu pembuat ekspresi menghasilkan KeyConditionExpression dan ExpressionAttributeValues dipetakan jadi awalannya cocok dengan apa yang sebenarnya Anda tulis.

Membebani indeks juga

Trik yang sama berlaku untuk . Berikan nama kunci umum — gsi1pk, gsi1sk — dan biarkan setiap entitas menulis apa pun yang diperlukannya. Salah satu indeks kemudian menjawab pola tersebut tabel dasar tidak bisa.

pkskgsi1pkgsi1sk
TENANT#acmeINVOICE#2026-0015STATUS#open2026-06-30
TENANT#acmeINVOICE#2026-0014STATUS#paid2026-06-12
TENANT#betaINVOICE#2026-0099STATUS#open2026-06-25

Sekarang Query gsi1 WHERE gsi1pk = "STATUS#open" mencantumkan setiap faktur terbuka di seluruhnya penyewa, tanggal jatuh tempo dipesan — tampilan lintas partisi cakupan penyewa tabel dasar kunci tidak akan pernah bisa berfungsi. Entitas yang berbeda dapat menggunakan kembali gsi1 dengan maknanya sendiri (katakanlah gsi1pk = "ROLE#admin"), jadi satu indeks mencakup beberapa pembacaan. Ingat saja a GSI akhirnya konsisten — penulisannya tertinggal dari tabel dasar.

Lakukan di DynoTable

Kunci mentah yang kelebihan beban tidak dapat dibaca: INVOICE#2026-0015 dan EVENT#2026-06-23T09:12Z kabur bersama dalam daftar datar. Penampil yang dikelompokkan berdasarkan partisi dan permukaan awalan mengubah laci sampah kembali menjadi entitas.

<gambar kelas="doc-media-placeholder" jenis data="tangkapan layar" data-src="docs/guide-dynamodb-key-overloading-collection.png"

DynoTable menjelajahi koleksi item salah satu penyewa — item META, USER, INVOICE, dan EVENT yang dikelompokkan dalam satu kunci partisi yang kelebihan beban.

Jebakan

  • Pilih pembatas sekali dan jangan pernah mengubahnya. # adalah konvensinya. Mencampur # dan : di seluruh entitas merusak begins_with dengan cara yang tidak Anda pedulikan.
  • Jangan membebani nilai yang memerlukan matematika rentang secara berlebihan. Kunci pengurutan INVOICE#2026-0015 mengurutkan secara leksikal, bukan numerik — ID dan menggunakan ISO-8601 tanggal sehingga urutan string sesuai dengan urutan yang Anda maksud.
  • Cadangan namespace awalan. Dua jenis entitas yang keduanya memulai USER (misalnya USER# dan USERGROUP#) akan bertabrakan di bawah begins_with(sk, "USER"). Membuat awalan yang tidak ambigu dari karakter pertama.
  • Rencanakan pembacaan sebelum kunci. Overloading menyajikan pola akses yang Anda miliki disebutkan. Jika Anda belum mengetahui bacaan Anda, lihat desain meja tunggal terlebih dahulu — kuncinya ada di bagian hilir dari pertanyaan.

Petakan partisi, lalu unduh DynoTable untuk menelusuri partisi Anda sendiri kunci yang kelebihan beban dan lihat satu Query menarik kembali seluruh penyewa sekaligus.

Biaya kueri pada partisi yang kelebihan beban

Mencantumkan setiap anggota di bawah TENANT#acme dengan begins_with(sk, "USER#") hanya membaca baris pengguna — bukan faktur atau peristiwa — karena kondisi kunci memfilter sebelum data meninggalkan partisi. Pada penyewa dengan 200 pengguna (masing-masing 2 KB) dan 5.000 peristiwa audit (masing-masing 1 KB), kueri tersebut menyentuh ~400 KB (~100 RCU yang pada akhirnya konsisten). Sebuah Scan di seluruh meja untuk menemukan pengguna akan mengukur setiap item di setiap penyewa.

Tempelkan item yang kelebihan muatan ke dalam kalkulator ukuran item, lalu daftar perkiraan kueri di kalkulator harga.

Desain dengan alat meja tunggal

Masukkan entitas (Penyewa, Pengguna, Faktur, Acara) dan pola akses ("daftar pengguna untuk penyewa", "faktur terbuka di seluruh penyewa") ke dalam alat desain meja tunggal. Ini mengusulkan Templat pk/sk dan kunci GSI yang cocok dengan awalan kelebihan beban yang akan Anda gunakan dalam produksi — sebelum Anda melakukan CloudFormation.

Keluarkan pertanyaan dari pola

Setelah awalan diperbaiki, buat kondisi utama di pembuat ekspresi dan ekspor paginasi program dari pembuat kueri. Kesalahan awalan (USER# vs USERS#) mengembalikan set kosong tanpa kesalahan — ekspresi yang dihasilkan mengurangi mode kegagalan senyap itu.

Registri awalan tipe entitas

Pertahankan tabel internal singkat yang dapat dijadikan referensi oleh pengembang:

KesatuanUrutkan awalanContoh SKPotongan kueri
Meta penyewaMETAMETADapatkan satu item
PenggunaUSER#USER#u_3001begins_with(sk, "USER#")
FakturINVOICE#INVOICE#2026-0015begins_with(sk, "INVOICE#")
PeristiwaEVENT#EVENT#2026-06-23T09:12Zekor yang dipesan berdasarkan waktu dengan descending dibaca

Tipe entitas baru harus memilih awalan yang tidak berbenturan di bawah begins_with awalan yang ada — USER# dan USERGROUP# keduanya cocok dengan begins_with(sk, "USER") kecuali Anda memanjangkan atau memisahkan pembatas dengan hati-hati.

Diperbarui