DynamoDB'de COUNT, SUM ve Toplama Nasıl Yapılır
DynamoDB'nin tam olarak tek bir yerleşik toplaması vardır: Select=COUNT ile eşleşen
item'ları saymak. Yerel bir SUM, AVG, MIN veya MAX yoktur. Ve
alabildiğiniz sayım bile saydığı her item'ı okur (ve faturalandırır). Bu kılavuz
gerçekte neyin desteklendiğini, insanların başvurduğu yaklaşıklıkları ve ihtiyaç
duyduğunuzda bir tablo üzerinde gerçek COUNT/SUM/AVG'nin nasıl çalıştırılacağını
ele alır.
DynamoDB SUM, COUNT ve toplama işlevlerini yapabilir mi?
Çoğunlukla hayır. DynamoDB'nin tek yerleşik toplaması Select=COUNT'tur; eşleşen item sayısını döndürür ama yine de her item'ı okur (ve faturalandırır). Yerel bir SUM, AVG, MIN veya MAX yoktur ve PartiQL de hiçbirini eklemez. GROUP BY ile gerçek toplamalar için uygulamanızda toplayın, bir sayaç tutun veya DynoTable'ın Workbench'inde SQL çalıştırın.
Select=COUNTeşleşen item sayısını döndürür, ancak DynamoDB onu üretmek için yine de her item'ı okur — ucuz bir "sayım" maliyeti değil, tamScan/Queryokuma maliyetini ödersiniz.- Yerel bir
SUM,AVG,MINveyaMAXyoktur. DynamoDB'nin okuma işlemleri item döndürür; onları bir sayıya katlamaz. PartiQL de toplama eklemez. DescribeTable.ItemCountücretsizdir ama yaklaşıktır ve yalnızca "yaklaşık olarak her altı saatte bir" güncellenir — bir gösterge panosu kutusu için uygun, kesin bir şey için yanlış.- Kesin
COUNT/SUM/AVG/MIN/MAX(GROUP BYile) için, uygulamanızda toplayın, bir sayaç tutun veya DynoTable'ın SQL Workbench'inde çalıştırın (aşağıda).
Item'ları sayma: Select=COUNT
Hem Query hem Scan bir Select parametresi kabul eder. Onu COUNT olarak
ayarlayın ve yanıt item'lar yerine sayıları taşır:
aws dynamodb scan \
--table-name Orders \
--select COUNT \
--filter-expression "#s = :open" \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":open":{"S":"OPEN"}}'Yanıt size iki sayı verir (AWS: Sonuçlardaki item'ları sayma):
Count— "bir filtre ifadesi (varsa) uygulandıktan sonra kalan item sayısı."ScannedCount— "herhangi birScanFilteruygulanmadan önce değerlendirilen item sayısı." Filtre yoksa,ScannedCountCountile aynıdır.
Yalnızca partition key'iniz varsa ve içindeki yinelenenleri saymanız gerekiyorsa,
geçirdiğiniz koşul + filtre tam olarak
DynamoDB Expression Builder'ın ürettiği şeydir —
yukarıdaki KeyConditionExpression, FilterExpression ve ExpressionAttributeNames/Values
haritaları — JSON'u elle kaçışlamadan.
Büyük tabloları sayan insanları ısıran iki tuzak daha:
- 1 MB sayfa sınırı hâlâ geçerlidir. "
Scansonuç kümesinin boyutu 1 MB'tan büyükse,ScannedCountveCounttoplam item'ların yalnızca kısmi bir sayımını temsil eder" (AWS Scan dokümanları). Gerçek sayıyı elde etmek içinLastEvaluatedKey→ExclusiveStartKeyile sayfalama yapmanız ve çalışan bir toplam tutmanız gerekir — aynı döngü DynamoDB sayfalama'da ele alınmıştır. - Dar bir
Query, birScan'i yener. BirQueryüzerindekiSelect=COUNTyalnızca hedeflenen partition'daki item'ları metreler, tüm tabloyu değil. Bir partition key'i (temel tablo veya bir GSI) sabitleyebiliyorsanız, orada sayın — saymaya uygulanan Query ve Scan maliyet farkıdır.
Select=COUNT ve ItemCount (ve neden bayat)
DescribeTable, ücretsiz olarak, okuma maliyeti olmadan bir ItemCount (ve
TableSizeBytes) döndürür. Püf noktası
API referansının kendisindedir:
"DynamoDB bu değeri yaklaşık olarak her altı saatte bir günceller. Son değişiklikler
bu değere yansımayabilir." Bu yüzden tablonuzun gerçek durumunun epeyce gerisinde
kalabilir.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| Kesinlik | Kesin (eşleşen küme için) | Yaklaşık |
| Tazelik | Canlı | ~her 6 saatte bir güncellenir |
| Maliyet | Sayılan her item'ı okur + faturalandırır | Ücretsiz (meta veri) |
| Bir alt kümeyi filtreleyebilir / sayabilir | Evet (filtre ifadesi) | Hayır — yalnızca tüm tablo |
"Bu tablo ne kadar büyük" kabaca bir kontrol veya bir gösterge panosu kutusu için
ItemCount kullanın. Kesin, filtrelenmiş veya güncel bir sayıya ihtiyacınız olduğunda
Select=COUNT kullanın — ve okuma maliyetini kabul edin. Gerçekten canlı ve ücretsiz
herhangi bir şey için, bir sayacı kendiniz izleyin
(aşağıdaki Toplama kalıpları'na bakın).
Neden yerel bir SUM/AVG/MIN/MAX yok
DynamoDB'nin okuma işlemleri item döndürür. Bir sonuç kümesini bir skalere katlayacak
bir sorgu planlayıcısı yoktur, bu yüzden bir SUM veya AVG hesaplayacak bir şey de
yoktur. Sayma, API'nin sunduğu tek katlamadır, Select=COUNT aracılığıyla.
PartiQL bunu değiştirmez.
PartiQL SELECT dilbilgisi
SELECT {{expression}} [, …] FROM {{table}}[.{{index}}] [WHERE …] [ORDER BY {{key}} …]
şeklindedir; burada ifade, "* joker karakterinden veya bir veya daha fazla attribute
adı ya da belge yolundan oluşan bir projeksiyon listesinden oluşturulan bir
projeksiyondur." Bu dilbilgisinde toplama işlevi ve GROUP BY yan tümcesi yoktur — ve
ORDER BY bir {{key}} alır, "döndürülen sonuçları sıralamak için kullanılacak bir
hash key veya bir sort key" olarak belgelenmiştir. Her PartiQL SELECT yine bir
GetItem, Query veya Scan'e derlenir, bu yüzden
SELECT SUM(total) FROM "Orders" basitçe ifade edilemez. (PartiQL tavanı hakkında
daha fazlası PartiQL ve SQL'de.)
Toplama kalıpları (sayaçlar, stream'ler, uygulama tarafı)
DynamoDB sizin için toplama yapmayacağından, yerleşik kalıplar işi başka yere iter:
- Tutulan sayaç item'ı. Özel bir item tutun (örn.
PK = "STATS#orders") ve her yazmada birUpdateItemile sayısal bir attribute'aADDyapın. Toplamı okumak ardından tek birGetItem'dır — kesin ve ucuz, ama artırma mantığına, tutarlılığına ve bir sayaç sürekli vurulursa çekişmeye siz sahipsiniz. - DynamoDB Streams → toplayıcı. Bir stream etkinleştirin ve item'lar değiştikçe
çalışan toplamları (sayılar, toplamlar) güncelleyen bir Lambda'ya bağlayın.
AWS Streams dokümanları'na
göre, her kaydın
NEW_AND_OLD_IMAGEStaşıması için stream'inStreamViewType'ını yapılandırabilirsiniz — "item'ın hem yeni hem de eski görüntüleri" — yeniden taramadanSUMtarzı toplamaları güncel tutmaya yeter. Stream kayıtları 24 saatlik bir ömre tabidir ("bir parçadaki stream kayıtları 24 saat sonra otomatik olarak kaldırılır"), bu yüzden tüketicinin ayak uydurması gerekir. - Uygulama tarafı katlama. Eşleşen item'lar arasında sayfalayın ve
SUM/AVG/MIN/MAX'ı kendi kodunuzda biriktirin. Doğru, ama her seferinde her item'ı okur (ve faturalandırır) —Select=COUNTile aynı maliyet profili, artı veri aktarımı. - Analitiğe devretme. Yoğun veya geçici analitik toplama için, tabloyu S3'e dışa aktarın ve Athena ile sorgulayın ya da bir veri ambarına aktarın. AWS S3'e dışa aktarma dokümanları'na göre, dışa aktarma "okuma kapasite birimleri tüketmez" ve "Athena gibi AWS hizmetlerini kullanarak analitik ve karmaşık sorgular gerçekleştirmenize" izin verir — istek başına toplamayı aştığınızda AWS'nin önerdiği yol.
Her biri basitliği ya yazma zamanı kayıt tutmayla (sayaçlar, stream'ler) ya da okuma
zamanı maliyetiyle (uygulama tarafı taramalar) takas eder. Hiçbir kalıp DynamoDB'nin
kendisinin ücretsiz bir SUM hesaplamasını sağlamaz. Bu ödünleşimin gruplama sürümü —
tüm tablo yerine anahtar başına toplama — kendi kılavuzudur:
DynamoDB GROUP BY.
DynoTable'ın SQL Workbench'inde COUNT/SUM/AVG çalıştırma
Sadece cevaba ihtiyacınız olduğunda — "kaç OPEN sipariş var ve toplamları ne" — sayfalayan bir tarama döngüsü ya da bir Lambda yazmadan, DynoTable'ın SQL Workbench'i gerçek toplamalar çalıştırır. Tablolarınızı DynamoDB'nin gerçek Query/Scan çalışma zamanı üzerinden materyalize eder, ardından tüm SQL'inizi üstünde çalıştırır: DynamoDB'nin erişim modeli kuralları içinde SQL.
-- Runs in the DynoTable Workbench (NOT in PartiQL):
SELECT status,
COUNT(*) AS orders,
SUM(total) AS revenue,
AVG(total) AS avg_order,
MIN(total) AS smallest,
MAX(total) AS largest
FROM orders
GROUP BY status
ORDER BY revenue DESCBu, COUNT, SUM, AVG, MIN, MAX, GROUP BY ve ORDER BY'dır — hiçbirini
DynamoDB veya PartiQL ifade edemez — tek bir ifadede. Bu,
DynamoDB için SQL ile aynı analitik kamadır; tam gruplama
hikâyesi için DynamoDB GROUP BY'a bakın.
Workbench, alttaki erişim modeli hakkında dürüsttür, bir Postgres taklidi değildir:
- Satırlar yine DynamoDB'nin gerçek Query/Scan'i üzerinden gelir. Tüm bir tablo
üzerindeki bir
GROUP BYyine altta birScan'dir — Workbench o maliyeti gizlemek yerine açığa çıkarır, aynı Query ve Scan ödünleşimi. - Toplamalar, satırlar yerleştikten sonra materyalize edilen skaler attribute'lar üzerinde çalışır.
SSS
DynamoDB'de tarama yapmadan item'ları sayabilir miyim?
Tam olarak değil. Kesin, güncel bir sayım için item'ları okumalısınız —
Select=COUNT yine sayılan her item'ı metreler. Tek tarama-yapmayan seçenekler,
yaklaşık DescribeTable.ItemCount (~her 6 saatte bir güncellenir) veya her yazmada
kendinizin tuttuğu bir sayaç item'ıdır.
Bir GSI'ye göre item'ları nasıl sayarım?
İndeks üzerinde Select=COUNT ile Query (veya Scan) çalıştırın. Dar bir GSI
partition'ı üzerinden saymak, temel tabloyu taramaktan çok daha ucuzdur, çünkü
yalnızca o indeks partition'ındaki item'ları okursunuz — indeksi ihtiyaç duyduğunuz
sayım etrafında modelleyin.
DescribeTable.ItemCount doğru mu?
Yaklaşıktır.
API referansı,
DynamoDB'nin ItemCount ve TableSizeBytes'ı "yaklaşık olarak her altı saatte bir"
güncellediğini ve "son değişikliklerin bu değere yansımayabileceğini" belirtir. Kesin
veya canlı bir sayının önemli olduğu yerde kullanmayın.
DynamoDB SUM veya AVG yapabilir mi?
Yerel olarak değil ve PartiQL'de değil —
PartiQL SELECT dilbilgisi
toplama işlevlerine sahip değildir. Uygulamanızda toplayın, bir sayaç tutun (isteğe
bağlı olarak DynamoDB Streams aracılığıyla) ya da SUM/AVG'yi DynoTable'ın SQL
Workbench'inde çalıştırın.
Count ile ScannedCount arasındaki fark nedir?
ScannedCount, DynamoDB'nin filtrenizden önce kaç item değerlendirdiğidir; Count,
ondan sonra kaçının kaldığıdır. Filtre ifadesi olmadığında eşittirler. Aralarındaki
büyük bir fark, verimsiz bir sayım anlamına gelir.
DynamoDB verilerinizi bir tarama döngüsü yazmadan toplamak, ortalamasını almak veya gruplamak mı gerekiyor? DynoTable'ı indirin ve bir Workbench sekmesinde çalıştırın. Önce istemcileri mi karşılaştırıyorsunuz? Düz bir DynamoDB GUI karşısında nerede durduğuna bakın.