Sparse index DynamoDB
Sparse index adalah secondary index yang hanya menampung item yang membawa atribut key-nya — sehingga subset kecil dan panas dari tabel besar menjadi koleksi sendiri yang sudah terfilter dan siap di-Query.
Anda punya jutaan baris, tetapi query yang dijalankan sepanjang hari hanya menyentuh irisan tipis: tiket support terbuka, invoice belum dibayar, akun yang ditandai untuk review.
Memfilter irisan itu tetap men-Scan seluruh tabel dan menagih setiap baca. Sparse index membuat indeksnya sendiri yang kecil.
Apa itu sparse index di DynamoDB?
Sparse index adalah secondary index yang hanya menampung item yang membawa atribut key-nya. Karena DynamoDB melewatkan item yang tidak punya key itu, Anda menciptakan key yang hanya ditulis item yang diinginkan — tiket terbuka, invoice belum dibayar — dan indeks menjadi tepat subset itu. Query lalu hanya membacanya, tanpa filter, tanpa kapasitas baca terbuang.
- Secondary index hanya mengindeks item yang punya key-nya. Hilangkan key pada item dan item itu tidak pernah masuk indeks — tanpa placeholder, tanpa baris null.
- Jadi Anda menciptakan key yang hanya dibawa item yang diinginkan. Tulis pada item yang Anda Query, hapus pada sisanya. Indeks menjadi tepat subset itu.
- Query hanya membaca subset, tanpa filter. Ukurannya mengikuti set panas yang kecil, bukan total tabel.
REMOVEadalah tuasnya, bukan mengosongkan. String kosong bukan key indeks yang valid — DynamoDB menolak seluruh write dengan ValidationException — jadi Anda harus menghapus atributnya.
Masalahnya: filter tidak menghemat baca
Datang dari SQL, Anda menganggap klausa WHERE mempersempit kerja.
FilterExpression DynamoDB tidak. Ia berjalan setelah item dibaca, bukan
sebelum.
Menurut AWS Developer Guide, "sebuah Query memakan jumlah kapasitas baca yang sama, terlepas dari ada atau tidaknya filter expression" — Anda membayar setiap item yang diperiksa, lalu membuang yang tidak cocok.
Jadi jika 50 dari 5 juta tiket Anda terbuka, Query/Scan berfilter membaca
jutaan untuk menyerahkan 50 itu.
Itulah jebakan di balik setiap thread "kenapa scan saya mahal"; query vs. scan punya gambaran biaya lengkapnya.
Sparse index menghindarinya dengan membuat indeksnya sendiri yang kecil.
Cara kerja sparsitas
Secondary index hanya mengindeks item yang benar-benar punya atribut key indeksnya.
Dokumen AWS tentang sparse index menjelaskannya: DynamoDB menulis item ke secondary index hanya ketika item itu membawa atribut key indeks, jadi indeks atas atribut yang jarang di-set tetap kecil secara alami.
Hilangkan partition key (atau sort key) GSI pada item dan DynamoDB tidak menulisnya ke indeks. Tanpa placeholder, tanpa baris null — item absen.
"Absen secara default" itulah seluruh tipunya. Jangan indeks atribut status
yang dibawa setiap item. Ciptakan atribut yang hanya dibawa item yang ingin
Anda Query.
Indeks lalu menjadi daftar bersih tepat item-item itu, dan Query terhadapnya
hanya membaca mereka — tanpa filter, tanpa kapasitas terbuang.
Bayangkan tabel dasar mengisi indeks, di mana hanya item yang membawa key yang menyeberang:
Hanya item ber-key (open) yang mereplikasi ke indeks; item closed tidak pernah masuk.
Ini mindset pembentukan key yang sama dengan single-table design: key adalah alat yang Anda bangun untuk access pattern spesifik, bukan cermin setia data Anda.
Contoh kerja: "hanya tiket terbuka"
Ambil tabel tiket support. Tabel dasar di-key untuk mengambil tiket by id dan mendaftar tiket pelanggan:
| PK | SK | attributes |
|---|---|---|
| TICKET#a91f | DETAIL | subject, body, priority, openState |
| CUSTOMER#88 | TICKET#a91f | subject, priority, openState |
Sepanjang umur tabel, sebagian besar tiket berakhir closed. Tetapi query dashboard yang di-hit agen sepanjang hari adalah "tampilkan setiap tiket terbuka, tertua dulu" — beberapa ratus baris tersembunyi di dalam jutaan.
Definisikan dengan partition key openBucket dan sort key
openedAt, dan hanya tulis openBucket pada tiket terbuka. Set saat tiket
dibuat; REMOVE saat tiket selesai.
| PK | SK | openBucket | openedAt | |
|---|---|---|---|---|
| TICKET#a91f | DETAIL | OPEN | 2026-06-23T09:14:00Z | ← open: in the index |
| TICKET#b02c | DETAIL | OPEN | 2026-06-22T16:40:00Z | ← open: in the index |
| TICKET#77de | DETAIL | (absent) | 2026-05-30T11:02:00Z | ← closed: NOT in the index |
Tiket a91f dan b02c membawa openBucket, jadi mereka hidup di GSI. Tiket
77de sudah resolved dan openBucket-nya dihapus, jadi diam-diam keluar.
Dashboard sekarang satu query murah:
Query IndexName = "open-tickets-index"
KeyConditionExpression: openBucket = "OPEN"
ScanIndexForward: true # oldest first
Ini hanya membaca tiket terbuka. Saat tiket close, indeks menyusut sendiri — ukurannya mengikuti populasi open, bukan total.
Satu nilai partisi statis ("OPEN") cocok di sini justru karena set-nya tetap
kecil. Set open yang besar butuh partition key ter-shard, tetapi indeks "subset
kecil" tepat di mana satu nilai adalah pilihan yang benar.
Transisi yang membuatnya bekerja adalah satu — menghapus atribut saat tiket selesai.
Prototype klausa REMOVE itu dan key condition bertipe untuk sisi baca di
DynamoDB Expression Builder, alih-alih
merakit sendiri ExpressionAttributeNames dan placeholder :val.
Lakukan di DynoTable
Bagagian sulit sparse index adalah melihat item mana yang masuk indeks versus mana yang diam-diam keluar.
DynoTable membiarkan Anda mengalihkan tampilan tabel ke secondary index dan
melihat tepat subset yang terisi. Jadi Anda bisa memastikan tiket yang resolved
benar-benar meninggalkan open-tickets-index, bukan tertinggal dengan key basi.

Jebakan dan langkah selanjutnya
Beberapa hal yang perlu diwaspadai:
- Hapus key-nya, jangan dikosongkan. String kosong bukan key indeks yang
valid — menulis
openBucket = ""gagal dengan ValidationException, jadi item tidak pernah terindeks dengannya. Untuk mengeluarkan item dari indeks Anda harusREMOVEatributnya. - Indeks bersifat . GSI di-update secara asinkron, jadi tiket yang baru resolved bisa sebentar masih muncul — baca GSI hanya mendukung eventual consistency. Jangan andalkan untuk "apakah tiket ini open sekarang".
- Perhatikan atribut yang di-.
Querypada indeks hanya mengembalikan atribut yang diproyeksikan ke dalamnya. Jika dashboard butuh subject dan priority, project mereka — atau bayarGetItemekstra untuk item dasar penuh. - GSI dan LSI bisa sparse — tuasnya sama: hilangkan sort key indeks pada item yang tidak ingin diindeks. GSI biasanya lebih cocok: Anda bisa menambahkannya setelah tabel dibuat dan memberinya skema key serta kapasitas sendiri. GSI vs. LSI merinci trade-off-nya.
Sparse index adalah salah satu ide tertua dalam model. Paper Amazon Dynamo 2007 membangun store di sekitar melayani access pattern ber-volume tinggi yang diketahui dengan murah.
Sparse index tepat itu: bentuk key sehingga query umum tidak membaca apa pun yang tidak dibutuhkannya.
Untuk membangun dan memeriksanya secara nyata, unduh DynoTable, arahkan ke tabel Anda, dan alihkan tampilan data ke GSI sparse Anda — saksikan subset berubah saat item mendapat dan kehilangan key indeks.


