Lanjutan7 menit baca

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:

WorkspaceEvents (base table)
EventPKEventSKactorIdverbtargetRef
WS#orbit-9TS#2026-06-23T14:02:11ZUSR#kpROLE_GRANTEDUSR#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:

ByActor (GSI) — its own partition space
actorIdEventSKEventPKverb
USR#kpTS#2026-06-23T14:02:11ZWS#orbit-9ROLE_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 GSIDari manaOpsional?
Partition + sort key GSIAtribut yang Anda namai sebagai key GSITidak
Key tabel dasarDisalin dari setiap item dasarTidak
Atribut yang diproyeksikanPilihan Projection AndaYa

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:

PutItemevent WS#orbit-9Commit kepartisi dasar200 OKke pemanggilJalur async:ekstrak key GSIRute ke partisiByActor USR#kpTulis atributyang diproyeksikan

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. Query GSI 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 Query mengembalikan 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.

Diperbarui