DynamoDB'de Sıfırla Doldurma (Zero-Padding) Sıralama Anahtarları
Bir DynamoDB dize sıralama anahtarı sözlüksel olarak sıralanır — soldan sağa,
her seferinde bir karakter — sayısal olarak değil. Yani "10", "2"den önce gelir,
çünkü "1", "2"den önce gelir. Sabit bir genişliğe sıfırla doldurma, dize
sırasını sayısal sırayla eşleştirmenin yoludur.
DynamoDB sıralama anahtarında "10" neden "2"den önce sıralanır?
Bir DynamoDB dize sıralama anahtarı, sayısal olarak değil, UTF-8 bayt sırasına göre sözlüksel biçimde karşılaştırılır. "1" baytı "2"den önce geldiğinden "10", "2"den önce sıralanır. Her sayıyı baştaki sıfırlarla sabit bir genişliğe doldurun — "2", "0000000002" olur — ve böylece dize sırası sayısal sırayla tam olarak eşleşir.
- Tuzak: dize olarak saklanan sayılar kelimeler gibi sıralanır.
"100","11","2", DynamoDB'nin size verdiği sıradır — kastettiğiniz şey değil. - Çözüm: her sayıyı baştaki sıfırlarla sabit bir genişliğe doldurun, böylece
"2","0000000002"olur. Artık sözlüksel ve sayısal sıra uyuşur. - Genişliği bir kez seçin: onu saklayacağınız en büyük değer için boyutlandırın, sonra birkaç basamak ekleyin. Genişliği sonradan değiştirmek her anahtarı yeniden yazmak demektir.
- Azalan bedava: yüksekten düşüğe sıralamak için (liderlik tablosu durumu),
maxValue - valuesaklayın, yine sıfırla doldurulmuş — DynamoDB'nin nitelik başına sıralama yönü yoktur.
Dize sıralama anahtarları neden size ihanet eder
SQL'den geliyorsanız, bir tamsayı sütunu üzerinde ORDER BY score DESC "zaten
çalışır" — motor sütunun sayısal olduğunu bilir. DynamoDB'nin, Number türü olmayan
bir sıralama anahtarı için böyle bir lüksü yoktur.
DynamoDB, dize (S) sıralama anahtarlarını UTF-8 bayt sırasına göre
karşılaştırır,
AWS sıralama anahtarı belgelerine göre.
Büyüklük değil, baytlar. "9" (0x39), "10"'u geçer çünkü ilk baytı "1"'in
(0x31) baytını yener. Uzunluk önemsizdir — yalnızca ilk farklı bayt karar verir.
İşte tuzak: bir sayı bir dize sıralama anahtarının içinde yaşadığı anda, aralığı
gezen her Query, karışık görünen bir sırada satır döndürür.
Bir liderlik tablosu sıralama anahtarı oluşturun
Mevsimsel bir atari liderlik tablosu alın. Mevsim başına bir öğe koleksiyonu her oyuncunun koşusunu tutar ve en yüksek skorların önce gelmesini istersiniz.
Onu tek bir öğe koleksiyonunda bir bileşik anahtarla modelleyin:
leaderboardId(bölüm anahtarı) — örn.SEASON#2026-SPRING.rankKey(sıralama anahtarı) — sıfırla doldurulmuş skor artı bir eşitlik bozucu (tiebreaker).
Saf bir ilk deneme, ham skoru bir dize olarak saklar:
| leaderboardId | rankKey | playerHandle |
|---|---|---|
| SEASON#2026-SPRING | "9" | quickdraw |
| SEASON#2026-SPRING | "10" | ace_pilot |
| SEASON#2026-SPRING | "1500" | nightowl |
| SEASON#2026-SPRING | "240" | bytecrash |
SEASON#2026-SPRING üzerinde bir Query, onları bu bayt sırasında döndürür:
"10", "1500", "240", "9". 9 puanlık koşu en sonda oturur ve 1500 puanlık
koşu ortada gömülüdür. Bir liderlik tablosu için işe yaramaz.
Sabit bir genişliğe doldurun
Kaydedeceğiniz en büyük skor için yeterince geniş bir genişlik seçin, sonra sıfırla sola doldurun. Diyelim ki skorlar on milyonda sınırlanıyor — bu sekiz basamak, bu yüzden pay için on basamak kullanın:
| leaderboardId | rankKey | playerHandle |
|---|---|---|
| SEASON#2026-SPRING | "0000000009" | quickdraw |
| SEASON#2026-SPRING | "0000000010" | ace_pilot |
| SEASON#2026-SPRING | "0000000240" | bytecrash |
| SEASON#2026-SPRING | "0000001500" | nightowl |
Artık her anahtar aynı uzunlukta, bu yüzden bayt-bayt karşılaştırma ve sayısal
karşılaştırma aynı sırayı üretir. Artan Query, 9, 10, 240, 1500 verir. Matematik
sonunda baytlarla eşleşir.
Genişlik tek yönlü bir kapıdır. On basamağa doldurursanız ve bir skor sonradan onu
aşarsa, 11 basamaklı bir değer 10 basamaklı bir değerden önce sıralanır — her şeyi
yeniden kırarak — ve bunu düzeltmek her mevcut rankKey'i yeniden yazmak demektir.
Genişliği aşırı sağlayın; bedeli bir avuç bayttır.
Azalan sıralama: farkı saklayın
Bir liderlik tablosu en yüksek skoru önce ister. DynamoDB bir sıralama
anahtarını ScanIndexForward: false ile ileri ya da geri okuyabilir, bu yüzden
azalan genellikle okuma zamanı bir bayraktır — önce ona uzanın.
Ama bir öğe koleksiyonu karışık sıralama yönlerine hizmet etmek zorunda olduğunda ya
da okuma bayraklarından bağımsız olarak en yüksek skorun fiziksel olarak önce gelmesini
istediğinizde, sayının kendisini ters çevirin. maxValue - score'u, aynı genişliğe
sıfırla doldurulmuş olarak saklayın:
score inverted (9999999999 - score) rankKey
1500 9999998499 "9999998499"
240 9999999759 "9999999759"
10 9999999989 "9999999989"
9 9999999990 "9999999990"Ters çevrilmiş değer üzerinde artan bayt sırası artık orijinal skorları yüksekten
düşüğe verir: 1500, 240, 10, 9. Numara,
2007 Amazon Dynamo makalesinin
ruhundadır — anahtarlar opak baytlardır, bu yüzden niyeti baytların içine
kodlarsınız.
Bir eşitlik bozucu (tiebreaker) ekleyin
İki oyuncu eşitlik yapabilir. Çıplak bir doldurulmuş skor sıralama anahtarında çakışır ve ikinci bir yazma birincinin üzerine yazar (aynı PK + SK). Her koşunun ayrı bir öğe olması ve eşitliklerin belirleyici biçimde çözülmesi için benzersiz bir sonek ekleyin:
rankKey = "<paddedScore>#<paddedTimestamp>#<playerId>"Örneğin "0000001500#0000001719100800#p_8842". Aynı skor, daha erken zaman damgası
daha yüksek slotu kazanır — zaman damgasını da doldurun, yoksa az önce düzelttiğiniz
hatayı yeniden ortaya çıkarır.
DynoTable'da sıfırla doldurulmuş rankKey'e göre sıralanan sezon liderlik tablosuna
göz atabilir ve doldurulan değerlerin satırları doğru şekilde hizaladığını görebilirsiniz
— genişliklerin doğru olduğunun, onları yayınlamadan önceki kanıtıdır.
O bileşik anahtarı elle birleştirdiğinizde bir genişliği yanlış yazmak kolaydır. Bir
"mevsimin tepesi" Query'si için KeyConditionExpression'ı expression
builder içinde üretmek, siz genişliklerle deney
yaparken begins_with / between sözdizimini dürüst tutar.

Kaçınılması gereken tuzaklar
- Çok dar doldurma. Tüm şema, bir değer genişliği aştığı ilk anda çöker. En kötü durum için boyutlandırın, sonra basamak ekleyin.
- Okuma bayrağını unutmak. Yalnızca azalan okuyorsanız,
ScanIndexForward: falsetek ihtiyacınız olabilir — bir bayrak işi yaparken ters çevrilmiş anahtarlara uzanmayın. - Bir koleksiyonda karışık genişlikler. Bir sıralama aralığını paylaşan her anahtar aynı genişliği kullanmalıdır. Yeni satırları dolduran ama eskileri doldurmayan bir göç, onları yanlış biçimde araya yerleştirir.
- Yanlış bölümü doldurma. Bir bileşik anahtarda, sıralamaya katılan her sayısal bölümü doldurun — yalnızca skoru değil, hem skoru hem zaman damgasını.
Sonraki adımlar
Sıfırla doldurma, daha geniş sıralama anahtarı
tasarımı araç kutusundaki bir araçtır; bir anahtarı
birkaç desene hizmet etmek için aşırı yüklediğinizde onu öğe
koleksiyonlarıyla eşleştirin ve sıralama doğru olduğunda bir
Scan yerine kesin bir Query'ye yaslanın.
Şemayı yayınlamadan önce gerçek bir tabloya göz atmak ve sıfırla doldurulmuş sıralama anahtarlarınızın sayısal sıraya düşmesini izlemek için DynoTable'ı deneyin.


