DynamoDB Anahtar Koşulu İfadeleri
Bir anahtar koşulu ifadesi, bir Query'ye geçirdiğiniz
KeyConditionExpression'dır — isteğin, DynamoDB'nin item'ları bulmak için
kullandığı tek kısmıdır. Geri kalan her şey (filtreler, projeksiyonlar) okuma çoktan
ölçüldükten sonra çalışır.
DynamoDB'de anahtar koşulu ifadesi nedir?
Bir anahtar koşulu ifadesi, bir Query üzerindeki KeyConditionExpression'dır ve
DynamoDB'ye hangi item'ları okuyacağını söyler. bir
eşitlik olmalıdır (PK = :v); tek bir aralık operatörü
alır — =, <, <=, >, >=, BETWEEN ya da begins_with. Bir filtreden farklı
olarak, neyin okunacağına ve fatura kesileceğine o karar verir.
- bir eşitlik olmalıdır. Yalnızca
PK = :vve başka bir şey değil — aralık yok,begins_withyok,INyok. DynamoDB tek bir bölümü bulmak için onu hash'ler. - bir aralık operatörü alır.
=,<,<=,>,>=,BETWEENya dabegins_with— bir dilimlediğiniz yer burasıdır. - Bir filtre değildir. Bir anahtar koşulu neyin okunacağına ve fatura
kesileceğine karar verir; bir
FilterExpressionyalnızca okuma için ödedikten sonra sonucu kırpar. - Sıralama anahtarları bayt sıralıdır. Aralık operatörleri sözlüksel olarak karşılaştırır, bu yüzden sıralama anahtarı string'ini nasıl biçimlendirdiğiniz sizin sorgu gücünüzdür.
Bölüm anahtarı neden eşitliğe kilitli
DynamoDB item'ları, bölüm anahtarını fiziksel bir bölüme hash'leyerek depolar. Bir hash size bir konum verir, bir aralık değil — bu yüzden boyunca taranacak bir şey yoktur.
PK > :v ya da begins_with(PK, :v)'nin doğrudan reddedilmesinin nedeni budur.
Motor, tüm tabloyu okumadan "anahtarı X ile başlayan tüm bölümler"i yanıtlayamaz, ki
bu tam olarak önlemek için inşa edildiği Scan'dir.
SQL'den geliyorsanız, bu ters hissettirir: WHERE id LIKE 'order%' Postgres'te
önemsizdir. DynamoDB'de bölüm anahtarı, aranabilir bir sütun değil, bir adrestir.
Güç sıralama anahtarında yaşar
Bir bölüm içinde item'lar sıralama anahtarına göre sıralı depolanır. O sıralama, aralık operatörlerinin sömürdüğü şeydir — DynamoDB bir konuma arar ve ileri okur.
| Operatör | Okuduğu | Ne için kullanılır |
|---|---|---|
SK = :v | Bir tam item | Anahtarıyla belirli bir çocuk |
SK < / <= / > / >= :v | Açık uçlu bir dilim | "Bu noktadan sonraki her şey" |
SK BETWEEN :a AND :b | Kapalı bir aralık (dahil) | Sınırlı bir pencere — bir tarih aralığı |
begins_with(SK, :p) | Bir önek dilimi | PK altında bir tür ya da hiyerarşi |
Anahtarda LIKE, CONTAINS, ENDS_WITH yoktur. Alt string ve son ek eşleştirmesi
bayt sıralı değildir, bu yüzden tam bir okumaya zorlarlar — tasarım gereği, API buna
izin vermez. Alt string eşleştirmesi bir FilterExpression içinde contains()
aracılığıyla vardır (okuma için zaten ödediğiniz yerde); son ek eşleştirmesi sunucu
tarafında hiç yoktur — tersine çevrilmiş bir anahtar depolayın ya da istemci tarafında
filtreleyin. (AWS: Anahtar koşulu ifadeleri)
İşlenmiş bir örnek: bir sohbet uygulamasındaki mesajlar
Diyelim ki kanal tabanlı sohbet inşa ediyorsunuz. Tek tablo, kanala göre bölümlenmiş, mesaj zamanına göre sıralanmış. Orijinal anahtar şeması:
- Bölüm anahtarı
ChannelRef—CH#{channelId} - Sıralama anahtarı
PostedAt— bir ISO-8601 zaman damgası,MSG#2026-06-23T14:05:00Z
MSG# öneki, mesaj satırlarını sıralanabilir ve aynı kanal altında birlikte
konumlandırabileceğiniz diğer herhangi bir satır türünden (sabitlenmiş yapılandırma,
üyelik) ayrı tutar.
Bir kanalın en son mesajlarını yükleyin. Yalnızca bölüm anahtarı, en yeni önce:
KeyConditionExpression ChannelRef = :ch
ExpressionAttributeValues { ":ch": "CH#general" }
ScanIndexForward false
ScanIndexForward: false, sıralı koleksiyonu ters yönde dolaşır — istemci tarafında
sıralamadan "en yeni önce" almanın ucuz yolu.
begins_with ile belirli bir gün. Zaman damgası sıralama anahtarı olduğu ve metin
olarak depolandığı için, bir tarih öneki temiz bir dilimdir:
KeyConditionExpression ChannelRef = :ch AND begins_with(PostedAt, :day)
:ch "CH#general"
:day "MSG#2026-06-23"
Bu, 2026-06-23'teki her mesajı ve başka hiçbir şeyi okumaz — DynamoDB öneke arar ve sonundan düştüğünde durur. Bu yalnızca önek, bayt sıralı bir string'in gerçek bir sol sabitlemesi olduğu için çalışır.
BETWEEN ile kesin bir pencere. "14:00 saatindeki mesajlar" için, dahil bir aralık
bir öneki yener:
KeyConditionExpression ChannelRef = :ch AND PostedAt BETWEEN :lo AND :hi
:ch "CH#general"
:lo "MSG#2026-06-23T14:00:00Z"
:hi "MSG#2026-06-23T14:59:59Z"
BETWEEN her iki sınırda da dahildir, bu yüzden uç noktalarınızı bilinçli seçin —
buradaki bir birlik-hatası sessizce bir kenar mesajını düşürür ya da ikiye katlar.
Bu ifadelerin herhangi birini, ExpressionAttributeValues haritası sizin için
doldurulmuş olarak,
DynamoDB expression builder içinde kurup
kopyalayabilirsiniz — begins_with ve BETWEEN söz dizimini ilk seferde doğru almak
için kullanışlı.
Bu oluşturucu bir pk = … AND begins_with(sk, …) sorgusuna önceden ayarlanmıştır —
KeyConditionExpression'ın güncellenmesini görmek için operatörü değiştirin:
DynoTable'da görüntüleyin
Aynı anahtar koşulunu gerçek bir kanal bölümüne karşı çalıştırın. Bir bölüm anahtarı
filtresi ayarladığınız an, DynoTable bir Query yayınlar — böylece tüm koleksiyonu
değil, yalnızca o dilimi yüklersiniz.
Tuzak: bir anahtar koşulunu bir filtreyle karıştırmak
Pahalı hata, bir anahtarın işini yapmak için FilterExpression'a uzanmaktır. Bir
filtre PostedAt'e bile başvuramaz — o sıralama anahtarıdır ve DynamoDB bir anahtar
attribute'unda bir filtreyi bir ValidationException ile reddeder. Bu yüzden geçici
çözüm, tarihi düz, anahtar olmayan bir attribute'a (MessageDate) çoğaltmak ve onun
üzerinde filtrelemektir:
KeyConditionExpression ChannelRef = :ch
FilterExpression begins_with(MessageDate, :day)
Bu, yukarıdaki begins_with anahtar koşuluyla eşdeğer görünür ve aynı satırları
döndürür — ama önce tüm kanal bölümünü okur, sonra günün dışındaki her şeyi atar.
Tam okuma için fatura kesilirsiniz.
Filtreler okuma maliyetini asla azaltmaz. DynamoDB item'ları ölçtükten sonra
çalışırlar, filtreli bir Scan ile aynı ayağa sıkan silah.
Bir yüklem anahtar koşuluna gidebiliyorsa, oraya aittir.
Çözüm yukarı akıştadır: bir erişim deseni bir PK eşitliği artı bir sıralama anahtarı aralığı olarak ifade edilemiyorsa, bu bir modelleme sinyalidir. Ya sıralama anahtarını yeniden şekillendirin ya da desen için anahtarlanmış bir dizin ekleyin — anahtarları nasıl yerleştireceğiniz için bkz. GSI ile LSI ve single-table tasarımı.
Tuzaklar ve sonraki adımlar
- Bölüm anahtarı her zaman
='dir. Asla aralık yok. Bölümler arasında bir aralığa ihtiyacınız varsa, tek birQuery'yi aşmışsınızdır. - Sorgu başına bir sıralama anahtarı koşulu. İki sıralama anahtarı yüklemini
ANDyapamazsınız;BETWEENya dabegins_withseçin, ikisini birden değil. - Ayrılmış sözcükler takma ad gerektirir.
Timestampya daNameadlı bir anahtarExpressionAttributeNames(#ts) kullanmalıdır, aksi hâlde sorgu hata verir. (AWS: ayrılmış sözcükler) BETWEENdahildir. Her iki uç nokta da eşleşir — sınırlarınızı buna göre tasarlayın.
Anahtar koşullarınızı expression builder içinde taslaklayın, sonra onları kendi tablolarınıza karşı çalıştırmak ve her anahtar koşulunun tam olarak hangi dilimi döndürdüğünü görmek için DynoTable'ı deneyin.