Bagaimana GSI DynamoDB disimpan secara internal
bukan penunjuk kembali ke tabel Anda. Ia adalah tabel terpisah yang dikelola secara internal — partisi sendiri, skema key sendiri, kapasitas sendiri — yang DynamoDB jaga tetap sinkron dengan menyalin write ke dalamnya secara asinkron.
Datang dari SQL, indeks adalah B-tree yang dibaut ke tabel fisik yang sama, di-update di dalam transaksi yang sama. GSI mematahkan kedua asumsi itu, dan hampir setiap kejutan GSI bermuara pada satu fakta itu.
Bagaimana GSI DynamoDB disimpan?
GSI DynamoDB disimpan sebagai tabel terpisah yang dikelola secara internal — partisi, skema key, dan kapasitas sendiri — bukan sebagai penunjuk ke tabel dasar. DynamoDB menyalin setiap write ke indeks secara asinkron, menyimpan hanya key GSI, key tabel dasar, dan atribut yang di-.
- GSI adalah tabelnya sendiri. Ia punya ruang partisi sepenuhnya independen yang di-key by partition key GSI, bukan tabel dasar.
- Write mereplikasi secara asinkron. Write Anda commit ke tabel dasar dulu, lalu DynamoDB fan-out ke tiap GSI di jalur latar.
- Hanya atribut yang diproyeksikan yang disimpan. Indeks menampung key GSI, key dasar, plus atribut apa pun yang Anda project — tidak lebih.
- Key GSI tidak harus unik. Banyak item dasar bisa berbagi satu partition/sort key GSI; dasar adalah tiebreaker yang menjaga mereka berbeda.
Mulai dengan satu item dasar
Ambil audit log SaaS. Setiap aksi privileged di workspace menjadi event
immutable. Tabel dasar, WorkspaceEvents, di-key agar semua event workspace
hidup di satu , diurutkan by waktu:
| EventPK | EventSK | actorId | verb | targetRef |
|---|---|---|---|---|
| WS#orbit-9 | TS#2026-06-23T14:02:11Z | USR#kp | ROLE_GRANTED | USR#mara |
EventPK = "WS#orbit-9" mempartisi by workspace; EventSK adalah timestamp ISO
agar Query mengembalikan event satu workspace dalam urutan kronologis. Itu
melayani "tampilkan timeline workspace ini" dengan sempurna.
Ia tidak melayani yang lain. Anda tidak bisa bertanya "apa yang dilakukan
USR#kp lintas setiap workspace?" — actorId bukan key, jadi satu-satunya cara
menjawabnya di tabel dasar adalah Scan penuh.
Itulah access pattern yang GSI ada untuk ditambahkan.
Tambah GSI dan saksikan tabel kedua muncul
Definisikan GSI, ByActor, yang mempartisi ulang event yang sama by siapa yang
melakukannya:
ByActor (GSI)
partition key = actorId ("USR#kp")
sort key = EventSK ("TS#2026-06-23T14:02:11Z")
DynamoDB sekarang memelihara struktur fisik kedua. Event logis yang sama
disimpan dua kali — sekali di partisi WS#orbit-9 tabel dasar, dan lagi di
partisi USR#kp GSI:
| actorId | EventSK | EventPK | verb |
|---|---|---|---|
| USR#kp | TS#2026-06-23T14:02:11Z | WS#orbit-9 | ROLE_GRANTED |
Perhatikan apa yang ikut: key tabel dasar (EventPK, EventSK) disimpan di
setiap item GSI secara otomatis. Itulah bagaimana hit GSI bisa menunjuk Anda
kembali ke item penuh — dan mengapa indeks
KEYS_ONLY tetap menelan storage.
Apa yang sebenarnya hidup di GSI
Indeks tidak menyalin seluruh item. Setiap entri GSI menampung tepat tiga hal, dan Anda hanya mengontrol yang ketiga:
| Disimpan di GSI | Dari mana | Opsional? |
|---|---|---|
| Partition + sort key GSI | Atribut yang Anda namai sebagai key GSI | Tidak |
| Key tabel dasar | Disalin dari setiap item dasar | Tidak |
| Atribut yang diproyeksikan | Pilihan Projection Anda | Ya |
Projection adalah KEYS_ONLY, INCLUDE (daftar bernama), atau ALL. Query
pada GSI hanya bisa mengembalikan atribut yang ada di indeks.
Minta yang tidak diproyeksikan dan DynamoDB tidak mengambilnya secara transparan — Anda tidak mendapat apa pun untuk field itu. (Dokumen GSI AWS)
Itulah jebakan relasional terbalik: SQL akan join kembali ke heap untuk kolom yang hilang. GSI tidak pernah. adalah seluruh kontraknya.
Bagaimana write mencapai indeks
Replikasi adalah bagian yang paling mematahkan intuisi SQL. Write dasar dan update indeksnya bukan satu operasi atomik.
Saat Anda PutItem, DynamoDB commit secara durable ke tabel dasar, mengakui
write Anda, dan lalu menyebarkan perubahan ke jalur latar yang meng-update
tiap GSI. Acknowledgment tidak menunggu indeks.
Urutan peristiwa untuk write audit kita, dari atas ke bawah:
Pemanggil mendapat 200 OK di langkah tiga, sebelum langkah empat sampai enam
selesai — jadi Query pada ByActor di celah itu bisa melewatkan event brand-new.
Asinkroni itu by design. Ia datang dari garis keturunan paper Amazon Dynamo 2007, yang memilih availability di atas consistency sinkron. Konsekuensi penuhnya hidup di mengapa GSI eventually consistent.
Key GSI bukan unique key
Di SQL, secondary index non-unique adalah default dan yang unique adalah constraint yang Anda pilih. GSI kebalikannya: ia tidak punya jaminan uniqueness, pernah.
Dua event audit dari actor yang sama pada timestamp yang bertabrakan akan
berbagi GSI1PK dan GSI1SK yang sama. DynamoDB menyimpan keduanya — ia
membedakannya secara internal by primary key tabel dasar, yang selalu ikut.
Jadi Query GSI untuk satu actor pada satu momen bisa sah mengembalikan
beberapa item. Jika Anda mengasumsikan satu-baris-per-key seperti unique index
SQL, itulah jebakannya.
Saat Anda Query indeks,
DynamoDB Expression Builder menulis
KeyConditionExpression dengan name dan value yang di-escape dengan benar —
mis. mencocokkan satu actor sejak cutoff:
KeyConditionExpression: "#a = :actor AND #ts > :since"
ExpressionAttributeNames: { "#a": "actorId", "#ts": "EventSK" }
ExpressionAttributeValues: {
":actor": { "S": "USR#kp" },
":since": { "S": "TS#2026-06-01T00:00:00Z" }
}Kapasitas hidup bersama indeks, bukan tabel
Karena GSI adalah tabelnya sendiri, ia punya kapasitas baca dan tulis sendiri,
ditagih dan di-throttle terpisah dari tabel dasar. Baca dari ByActor
mengonsumsi unit baca GSI, bukan tabel.
Coupling terbalik adalah bagian yang menggigit. Setiap write tabel dasar juga menulis indeks, dan jika GSI tidak bisa menyerapnya, ia back-pressure write dasar. Mekanisme itu punya panduannya sendiri — saat GSI men-throttle write tabel dasar.
Inilah juga mengapa partition key GSI sama pentingnya dengan tabel dasar. Key GSI kardinalitas rendah menggumpalkan write ke satu partisi indeks bahkan saat write dasar tersebar sempurna — hot partition yang Anda ciptakan dengan re-keying.
Amplifikasi write GSI (ditagih)
Setiap write tabel dasar yang memproyeksikan ke GSI menelan WCU dasar + WCU
indeks on-demand di us-east-1. Item 1 KB dengan proyeksi ALL biasanya
menagih ~2 WCU total — satu untuk baris tabel, satu untuk salinan indeks.
KEYS_ONLY mengecilkan write indeks; ALL menggandakan storage dan write amp.
Model ukuran item dan proyeksi di
kalkulator harga.
Jebakan dan langkah selanjutnya
- Jangan harapkan atribut yang tidak diproyeksikan kembali.
QueryGSI hanya mengembalikan apa yang disimpan indeks. Jika Anda butuh item penuh, project atau ambil dari tabel dasar by key yang ikut. - Jangan perlakukan key GSI sebagai unik. Rencanakan
Querymengembalikan lebih dari satu item per key; primary key dasar adalah satu-satunya identitas nyata. - Jangan baca GSI tepat setelah write yang mengisinya. Jalur async berarti indeks mungkin belum menampilkan write Anda — baca tabel dasar saat Anda butuh read-your-own-writes.
- Ukuran kapasitas GSI dengan sengaja. Independen pada baca dan dependensi tersembunyi pada tulis.
Seluruh permainannya memilih bentuk key yang melayani pattern Anda — single-table design meng-overload satu GSI lintas banyak; GSI vs LSI membahas kapan local index cocok sebagai gantinya.
Bangun dan preview KeyConditionExpression GSI Anda di
DynamoDB Expression Builder, lalu
coba DynoTable untuk memeriksa atribut yang diproyeksikan indeks
dan menyaksikan write mereplikasi ke GSI di tabel Anda sendiri.