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/skdan 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_withadalah hasilnya. Awalan tipe pada kunci pengurutan memungkinkan satuQuerytarik seluruh entitas, atau satu bagiannya, tanpaScandan tanpa filter.- Biaya: keterbacaan. Dump
pk/skmentah 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:
| 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" |
Setiap baris berbagi pk = "TENANT#acme", sehingga membentuk satu — semuanya
terletak di lokasi yang sama, semua dapat dijangkau dalam satu partisi baca.
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.
| 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 |
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"
Jebakan
- Pilih pembatas sekali dan jangan pernah mengubahnya.
#adalah konvensinya. Mencampur#dan:di seluruh entitas merusakbegins_withdengan cara yang tidak Anda pedulikan. - Jangan membebani nilai yang memerlukan matematika rentang secara berlebihan. Kunci pengurutan
INVOICE#2026-0015mengurutkan 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(misalnyaUSER#danUSERGROUP#) akan bertabrakan di bawahbegins_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:
| Kesatuan | Urutkan awalan | Contoh SK | Potongan kueri |
|---|---|---|---|
| Meta penyewa | META | META | Dapatkan satu item |
| Pengguna | USER# | USER#u_3001 | begins_with(sk, "USER#") |
| Faktur | INVOICE# | INVOICE#2026-0015 | begins_with(sk, "INVOICE#") |
| Peristiwa | EVENT# | EVENT#2026-06-23T09:12Z | ekor 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.