Composite Sort Key di DynamoDB
Sebuah composite primary key adalah partition key plus sort key. Trik yang
membuatnya ampuh adalah apa yang Anda taruh di dalam sort key: encode sebuah
hierarki sebagai satu string berdelimiter, dan satu Query membaca seluruh
subtree dalam urutan sort — tanpa join, tanpa rekursi, tanpa round-trip kedua.
Bagaimana cara kerja composite sort key di DynamoDB?
Sebuah composite sort key mengemas sebuah hierarki ke dalam satu string berdelimiter — root/photos/2026/ — yang disimpan DynamoDB dalam urutan byte UTF-8. Karena tata letaknya sudah cocok dengan pohonnya, satu Query dengan begins_with(SK, "root/photos/") membaca seluruh subtree dalam urutan path. Tanpa join, tanpa rekursi, tanpa round-trip kedua — hanya sebuah prefix scan atas potongan yang berdampingan.
- Sort key adalah string yang dapat diurutkan, bukan sekadar ID. Kemas
sebuah path ke dalamnya —
root/photos/2026/— dan DynamoDB menyimpan item dalam partition itu dalam urutan byte UTF-8 secara otomatis. - Sebuah delimiter mengubah pencocokan prefix menjadi pembacaan subtree.
begins_with(SK, "root/photos/")mengembalikan setiap keturunan folder itu dalam satu query. - Sort key mendukung kondisi rentang, bukan filter arbitrer. Anda mendapat
begins_with,between,>,<— desain key-nya agar pembacaan yang Anda butuhkan adalah sebuah prefix atau rentang, bukan sebuahScan. - Delimiter-nya menanggung beban. Pilih satu yang tidak bisa muncul di dalam segmen path, atau dua cabang tak terkait akan bertabrakan.
Mengapa sort key adalah seluruh permainan
Datang dari SQL, Anda akan memodelkan pohon folder dengan self-join parent_id
lalu menelusurinya secara rekursif — satu query per level. Di DynamoDB itu
adalah jebakan N+1 terhadap key-value store yang tidak punya join.
DynamoDB menyimpan setiap item di bawah sebuah partition key yang diurutkan oleh sort key-nya, dalam urutan byte UTF-8 untuk string (AWS: Query key conditions). Jadi jika sort key Anda adalah path-nya, tata letak fisiknya sudah cocok dengan pohonnya. Sebuah pembacaan menjadi prefix scan atas potongan yang berdampingan — bukan penelusuran graf.
Itulah pergeserannya: sort key bukan pengenal yang Anda cocokkan persis. Ia adalah alamat yang dapat diurutkan. Desain ia dan query-nya muncul gratis.
Modelkan pohon file-system
Misalkan Anda menyimpan pohon file per akun. Satu drive per akun adalah partition alaminya; path di dalamnya adalah sort key-nya.
| PK | SK | node_type | bytes |
|---|---|---|---|
| DRIVE#a91 | root/ | folder | - |
| DRIVE#a91 | root/photos/ | folder | - |
| DRIVE#a91 | root/photos/2026/ | folder | - |
| DRIVE#a91 | root/photos/2026/beach.jpg | file | 284910 |
| DRIVE#a91 | root/photos/2026/sunset.jpg | file | 512004 |
| DRIVE#a91 | root/docs/ | folder | - |
| DRIVE#a91 | root/docs/taxes.pdf | file | 88210 |
Dua konvensi orisinal mengerjakan tugasnya di sini:
PK = DRIVE#<account>menyimpan seluruh pohon satu akun dalam satu item collection, sehingga setiap pembacaan subtree adalahQuerysingle-partition.SKadalah path lengkap dengan/di akhir pada folder. Slash di akhir disengaja — ia membuat sebuah folder terurut sebelum anak-anaknya sendiri dan menjagaroot/photos/tetap berbeda dari file saudara bernamaroot/photos.
Baca subtree dalam satu query
Daftarkan semua yang ada di bawah root/photos/ — folder, subfolder, dan file,
secara rekursif:
Query
KeyConditionExpression = PK = :drive AND begins_with(SK, :prefix)
:drive = "DRIVE#a91"
:prefix = "root/photos/"
Itu mengembalikan root/photos/, root/photos/2026/, beach.jpg, dan
sunset.jpg — dalam urutan path, dalam satu pembacaan yang ditagih. Anda hanya
membayar untuk item dalam potongan itu, bukan seluruh drive.
Di DynoTable, Anda menjalankan query begins_with ini persis terhadap sort key path dan
folder beserta seluruh keturunannya kembali dalam urutan path — tanpa sintaks placeholder
yang perlu ditulis sendiri.
Butuh KeyConditionExpression mentah (nama, nilai, dan begins_with) untuk kode Anda
sendiri? Bangun dan salin di
DynamoDB Expression Builder.

Daftarkan satu level, bukan seluruh subtree
begins_with memberi Anda pembacaan rekursif. Untuk daftar direktori
non-rekursif — anak langsung dari root/photos/ dan tidak lebih dalam — simpan
sebuah atribut depth dan tambahkan rentang sort-key plus sebuah filter, atau
pecah path ke dalam sebuah GSI parent. Versi paling sederhana: simpan sebuah
atribut parent (root/photos/) dan sebuah GSI ber-key padanya.
Intinya: sebuah sort key menjawab pertanyaan prefix dan rentang dengan
murah. "Hanya anak langsung" adalah pertanyaan berbeda — modelkan secara
eksplisit alih-alih berharap sebuah FilterExpression membuatnya efisien.
Sebuah filter berjalan setelah pembacaan dan Anda membayar setiap item yang
dibuangnya.
Pilih delimiter dengan hati-hati
Delimiter adalah bagian dari kontrak data Anda. Dua aturan:
- Ia tidak boleh muncul di dalam segmen path. Jika nama file bisa
mengandung
/,/adalah delimiter yang salah — file bernamaa/btak bisa dibedakan dari folderayang menampungb. Pilih byte tercadang (beberapa tim memakai#atau control char) dan larang ia di dalam segmen. - Perhatikan urutan sort di batas-batasnya.
/(0x2F) terurut sebelum digit dan huruf, yang biasanya itulah yang Anda mau untuk urutan pohon. Ubah delimiter-nya dan Anda mengubah pengurutannya — verifikasi terhadap data nyata.
Composite sort key vs. atribut sort terpisah
Composite sort key (root/photos/2026/x) | Plain ID sort key + atribut parent | |
|---|---|---|
| Pembacaan subtree | Satu query begins_with | Query rekursif (N+1) atau penelusuran GSI |
| Pengurutan | Urutan path, gratis | Harus menambah atribut sort eksplisit |
| Pindah / rename | Tulis ulang semua keturunan | Perbarui satu pointer parent |
| Daftar anak langsung | Butuh atribut depth atau GSI | Alami (parent = x) |
Composite key menang saat pembacaan berbentuk subtree dan pengurutan penting; model flat-ID menang saat pohonnya bermutasi terus-menerus. Sebagian besar hierarki read-heavy — pohon file, pohon kategori, bagan organisasi — condong ke composite.
Jebakan dan langkah berikutnya
- Jangan menjejali key berlebihan. Semua yang Anda encode bersifat imutabel dan terindeks hanya berdasarkan prefix. Atribut yang Anda query berdasarkan kesamaan tempatnya di field-nya sendiri atau sebuah GSI, bukan disumpalkan ke sort key.
- Sebuah sort key tidak bisa melakukan
WHEREarbitrer. Hanyabegins_with,between, dan perbandingan. Jika Anda mendapati diri menjangkau sebuahFilterExpression, Anda mungkin memodelkan key-nya salah — lihat Query vs. Scan. - Mendalami desain key ada di single-table design; untuk saat pembacaan subtree butuh sebuah indeks alih-alih base table, lihat GSI vs. LSI.
Bangun key condition begins_with dengan
Expression Builder, lalu
unduh DynoTable untuk menjalankan query prefix ini terhadap tabel
Anda sendiri dan amati sebuah subtree kembali dalam urutan path.


