DynamoDB'de Query ve Scan
Query, partition key ile tek bir item koleksiyonunu okur (isteğe bağlı olarak
sort key'i daraltarak); Scan ise tüm tabloyu okur ve sonradan filtreler.
API'de benzer görünürler, ancak tamamen farklı faturalandırılır — ve ölçeklenir.
DynamoDB'de Query mi yoksa Scan mi kullanmalıyım?
İhtiyacınız olan partition'ı adlandırabildiğiniz her durumda Query kullanın — tek bir item koleksiyonunu okur ve yalnızca eşleşen item'lar için faturalandırılır. Scan'e yalnızca tek seferlik dışa aktarımlar veya küçük tablolar için başvurun; her item'ı okur ve herhangi bir FilterExpression çalışmadan önce tüm tabloyu faturalandırır. Gerçek verilerde Query kazanır.
- Query hedeflidir: eşleşen partition'daki item'lar için ödeme yaparsınız.
- Scan kapsamlıdır: her item'ı okumak için ödeme yaparsınız, ardından çoğunu
okuma ölçüldükten sonra çalışan bir
FilterExpressionile atarsınız.
Gerçek boyutta herhangi bir tabloda, filtreli bir Scan, klasik "faturam neden
bu kadar yüksek ve gecikmem RDS'den daha kötü" tuzağıdır.
Yan yana
| Query | Scan | |
|---|---|---|
| Okumalar | Bir partition (PK ile) | Tablodaki her item |
| Faturalanan kapasite | Partition'da eşleşen item'lar | Tüm tablo, filtrelemeden önce |
FilterExpression | Okumadan sonra uygulanır — yine de okuma faturalanır | Aynı — filtreleme asla maliyeti kesmez |
| Gecikme | Tablo büyüdükçe sabit | Tablo boyutuyla büyür |
| Sayfalama | 1 MB/sayfa → LastEvaluatedKey | 1 MB/sayfa; paralelleştirilebilir |
| Şunun için kullanın | Bilinen erişim modelleri | Tek seferlik dışa aktarımlar, küçük yapılandırma tabloları |
Ana tuzak: bir FilterExpression, her iki işlemde de, DynamoDB okumayı
ölçtükten sonra çalışır. "10 satır döndüren" bir Scan, bir milyon okumak için
faturalandırabilir — filtreleme bir kolaylıktır, asla bir maliyet kontrolü değil.
Tam bir Scan gerçekte ne tutar
Üzerine sayılar koyalım. DynamoDB okumaları 4 KB'lik birimlerle ölçer: bir
okuma 4 KB başına bir
tüketir, bir
okuma ise bunun yarısını. Query ve
Scan, dokundukları her item'ın boyutunu toplar — döndürdükleri her
item'ın değil — ve bir sonraki 4 KB'ye yukarı yuvarlar.
Item başına ortalama 2 KB olan (~2 GB veri) 1 milyon item'lık bir tabloyu ve bu item'ların 10'una ihtiyaç duyan bir erişim modelini ele alalım:
| Okunan item | Ölçülen veri | Okuma birimleri (nihai tutarlı) | |
|---|---|---|---|
Scan + FilterExpression | 1,000,000 | ~2 GB | ~262,000 |
Eşleşen bir anahtarda Query | 10 | 20 KB | 3 |
Aynı 10 item, arada beş büyüklük mertebesi — ve Scan, filtre ister on item
ister hiçbirini eşleştirsin, her çalıştığında o ~262,000'i faturalandırır.
faturalandırmada bunlar doğrudan faturaya yazılan istek
birimleridir; tablolarda ise büyük bir Scan, verim
için üretim trafiğiyle rekabet eder ve onu kısıtlayıp
ProvisionedThroughputExceededException
hatasına sürükleyebilir.
İnsanları şaşırtan üç maliyet gerçeği daha:
Select: COUNTücretsiz değildir. Sayım yapan bir Query ya da Scan, item'ları okumakla tam olarak aynı okuma kapasitesini tüketir — yalnızca onları döndürmez.Limit, eşleşen item'ları değil, değerlendirilen item'ları sınırlar. Bir filtreyle birleştiğinde, bir sayfa yine de tam bir sayfalık okuma faturalandırırken boş dönebilir.- Asla tahmin etmek zorunda değilsiniz.
ReturnConsumedCapacity: TOTALgeçin; her yanıt, az önce tükettiği kapasiteyi raporlar.
Kendi item'larınızın ne kadar çektiğini item boyutu hesaplayıcısı ile kontrol edin, ardından okuma birimlerini fiyatlandırma hesaplayıcısı ile aylık bir faturaya çevirin.
Query kullanın
Query PK = "USER#42" AND SK begins_with "ORDER#"
Yaygın bir erişim modelini yanıtlamak için kendinizi Scan'e başvururken
buluyorsanız, bu bir modelleme sinyalidir: modelin bir Query haline gelmesi için
bir Global Secondary Index ekleyin.
Seçim tek bir soruya iner — ihtiyacınız olan partition'ı adlandırabiliyor musunuz?
Anahtar biliniyorsa Query yaparsınız; bilinmiyorsa onu bir Query yapmak için bir
GSI ekleyin ve yalnızca hiçbir anahtar uymadığında Scan'e geri dönün.
Scan ne zaman uygundur
Tek seferlik dışa aktarımlar, küçük yapılandırma tabloları ve tüm tablo arasında
bilerek sayfalama yapan arka plan işleri. Gerçekten her şeyi okumanız
gerektiğinde, bir Scan'i çalışanlar arasında bölmek için
Segment/TotalSegments kullanın (bir —
bkz. DynamoDB'de paralel Scan'ler) ve onu
LastEvaluatedKey ile düzgünce sayfalayın
(sayfalama rehberi). Sorun hâlihazırda çalıştırdığınız bir
Scan ise, Scan neden yavaş ve pahalı
triyajı adım adım anlatır.
DynamoDB üzerinde refleksif bir SELECT * FROM table, PartiQL kılığında aynı
anti-modeldir — bir Scan'e derlenir. Gerçekten item'lar arası analitik (bir
GROUP BY, bir JOIN, bir toplama) gerektiğinde, DynoTable'ın SQL Workbench'i
bunları tabloyu zorlamak yerine sınırlı bir sonuç kümesi üzerinde istemci tarafında
çalıştırır.
Bu sorguları kendi tablolarınıza karşı çalıştırmak ve incelemek için DynoTable'ı deneyin — çalıştırdığı her işlemin tükettiği kapasiteyi gösterir.