Zero-Padding Sort Key di DynamoDB
Sebuah sort key string DynamoDB terurut secara leksikografis — satu karakter
pada satu waktu, kiri ke kanan — bukan secara numerik. Jadi "10" mendarat
sebelum "2", karena "1" datang sebelum "2". Zero-padding ke lebar tetap
adalah cara Anda membuat urutan string cocok dengan urutan numerik.
Mengapa "10" terurut sebelum "2" pada sort key DynamoDB?
Karena sort key string DynamoDB dibandingkan secara leksikografis berdasarkan urutan byte UTF-8, bukan secara numerik. Byte untuk "1" mendahului "2", sehingga "10" mendarat sebelum "2". Pad setiap number ke lebar tetap dengan nol di depan — "2" menjadi "0000000002" — dan urutan string kemudian cocok dengan urutan numerik secara tepat.
- Jebakannya: number yang disimpan sebagai string terurut seperti kata.
"100","11","2"adalah urutan yang DynamoDB berikan — bukan yang Anda maksud. - Solusinya: pad setiap number ke lebar tetap dengan nol di depan, sehingga
"2"menjadi"0000000002". Kini urutan leksikografis dan numerik sepakat. - Pilih lebar sekali: ukur ia untuk nilai terbesar yang akan pernah Anda simpan, lalu tambah beberapa digit. Mengubah lebarnya nanti berarti menulis ulang setiap key.
- Menurun secara gratis: untuk mengurutkan tinggi-ke-rendah (kasus
leaderboard), simpan
maxValue - value, juga ter-zero-pad — DynamoDB tidak punya arah sort per-atribut.
Mengapa sort key string mengkhianati Anda
Datang dari SQL, sebuah ORDER BY score DESC atas kolom integer "tinggal jalan"
— engine tahu kolomnya numerik. DynamoDB tak punya kemewahan semacam itu untuk
sort key yang bukan tipe Number.
DynamoDB membandingkan sort key string (S) berdasarkan urutan byte UTF-8,
per dokumentasi sort-key
AWS.
Byte, bukan besaran. "9" (0x39) mengungguli "10" karena byte pertamanya
mengalahkan "1" (0x31). Panjang tidak relevan — hanya byte berbeda pertama yang
menentukan.
Itulah jebakannya: begitu sebuah number tinggal di dalam sort key string, setiap
Query yang menelusuri rentang mengembalikan baris dalam urutan yang tampak
teracak.
Bangun sort key leaderboard
Ambil sebuah leaderboard arcade musiman. Satu item collection per musim menampung setiap run pemain, dan Anda ingin skor teratas lebih dulu.
Modelkan ia dengan composite key dalam satu item collection:
leaderboardId(partition key) — mis.SEASON#2026-SPRING.rankKey(sort key) — skor yang ter-zero-pad plus sebuah tiebreaker.
Upaya naif pertama menyimpan skor mentah sebagai string:
| leaderboardId | rankKey | playerHandle |
|---|---|---|
| SEASON#2026-SPRING | "9" | quickdraw |
| SEASON#2026-SPRING | "10" | ace_pilot |
| SEASON#2026-SPRING | "1500" | nightowl |
| SEASON#2026-SPRING | "240" | bytecrash |
Sebuah Query pada SEASON#2026-SPRING mengembalikan mereka dalam urutan byte
ini: "10", "1500", "240", "9". Run 9-poin duduk di paling buntut dan run
1500-poin terkubur di tengah. Tidak berguna untuk leaderboard.
Pad ke lebar tetap
Pilih lebar yang cukup untuk skor terbesar yang akan pernah Anda catat, lalu left-pad dengan nol. Misalkan skor maksimal sepuluh juta — itu delapan digit, jadi gunakan sepuluh digit untuk ruang lebih:
| leaderboardId | rankKey | playerHandle |
|---|---|---|
| SEASON#2026-SPRING | "0000000009" | quickdraw |
| SEASON#2026-SPRING | "0000000010" | ace_pilot |
| SEASON#2026-SPRING | "0000000240" | bytecrash |
| SEASON#2026-SPRING | "0000001500" | nightowl |
Kini setiap key sama panjang, jadi perbandingan byte-demi-byte dan perbandingan
numerik menghasilkan urutan yang identik. Query menaik memberi 9, 10, 240, 1500. Matematikanya akhirnya cocok dengan byte-nya.
Lebar adalah pintu satu arah. Jika Anda mem-pad ke sepuluh digit dan sebuah skor
kemudian melampauinya, sebuah nilai 11-digit terurut sebelum yang 10-digit —
merusak ulang segalanya — dan memperbaikinya berarti menulis ulang setiap
rankKey yang ada. Over-provision lebarnya; biayanya hanya segenggam byte.
Urutkan menurun: simpan selisihnya
Sebuah leaderboard ingin skor tertinggi lebih dulu. DynamoDB bisa membaca
sebuah sort key maju atau mundur dengan ScanIndexForward: false, jadi menurun
biasanya sebuah flag saat-baca — jangkau itu lebih dulu.
Tapi saat satu item collection harus melayani arah sort campuran, atau Anda ingin
skor teratas secara fisik lebih dulu terlepas dari flag baca, balik number-nya
sendiri. Simpan maxValue - score, ter-zero-pad ke lebar yang sama:
score inverted (9999999999 - score) rankKey
1500 9999998499 "9999998499"
240 9999999759 "9999999759"
10 9999999989 "9999999989"
9 9999999990 "9999999990"Urutan byte menaik atas nilai terbalik kini menghasilkan skor asli
tinggi-ke-rendah: 1500, 240, 10, 9. Triknya ada dalam semangat paper Amazon
Dynamo 2007
— key adalah byte opak, jadi Anda meng-encode maksud ke dalam byte-nya.
Tambahkan tiebreaker
Dua pemain bisa seri. Sebuah skor ter-pad telanjang bertabrakan pada sort key, dan penulisan kedua akan menimpa yang pertama (PK + SK sama). Tambahkan sebuah suffix unik agar setiap run adalah item yang berbeda dan seri terselesaikan secara deterministik:
rankKey = "<paddedScore>#<paddedTimestamp>#<playerId>"Misalnya "0000001500#0000001719100800#p_8842". Skor sama, timestamp lebih awal
memenangkan slot lebih tinggi — pad timestamp-nya juga, atau ia memperkenalkan
ulang bug persis yang baru Anda perbaiki.
Di DynoTable, Anda dapat menelusuri leaderboard musim yang diurutkan berdasarkan
rankKey yang ter-zero-pad dan menyaksikan nilai-nilai yang ter-pad berbaris dengan
benar — bukti bahwa lebar sudah tepat sebelum Anda men-deploy-nya.
Saat Anda merakit composite key itu dengan tangan, mudah salah-pencet lebar.
Menghasilkan KeyConditionExpression untuk Query "puncak musim" di
expression builder menjaga sintaks
begins_with / between tetap jujur saat Anda bereksperimen dengan lebar.

Jebakan yang harus dihindari
- Padding terlalu sempit. Seluruh skema runtuh pertama kali sebuah nilai melampaui lebarnya. Ukur untuk kasus terburuk, lalu tambah digit.
- Lupa flag baca. Jika Anda hanya pernah membaca menurun,
ScanIndexForward: falsemungkin sudah cukup — jangan jangkau key terbalik saat sebuah flag melakukannya. - Lebar campuran dalam satu collection. Setiap key yang berbagi sebuah rentang sort harus memakai lebar yang sama. Sebuah migrasi yang mem-pad baris baru tapi bukan yang lama menyisipkan mereka secara salah.
- Mem-pad segmen yang salah. Dalam sebuah composite key, pad setiap segmen numerik yang berpartisipasi dalam pengurutan — skor dan timestamp keduanya, bukan hanya skornya.
Langkah berikutnya
Zero-padding adalah satu alat dalam perangkat desain
sort-key yang lebih luas; pasangkan ia dengan item
collection saat Anda meng-overload sebuah key untuk melayani
beberapa pola, dan andalkan sebuah Query yang presisi alih-alih sebuah
Scan begitu pengurutannya benar.
Coba DynoTable untuk menjelajahi tabel nyata dan amati sort key ter-zero-pad Anda jatuh ke urutan numerik sebelum Anda merilis skemanya.


