Başlangıç6 dakikalık okuma

Bir DynamoDB Scan Neden Yavaş ve Pahalıdır

Bir Scan, tablodaki her öğeyi okur ve yalnızca sonradan filtreler. SQL kas hafızasından uzandığın işlemdir ve geride bıraktığın RDS kutusundan daha kötü bir gecikme yaratırken sessizce faturanı şişiren işlemdir.

DynamoDB Scan'im neden yavaş ve pahalı?

Bir Scan, FilterExpression çalışmadan önce tablodaki her öğeyi okur; bu nedenle kaç satır döndüğünden bağımsız olarak tüm tabloyu okuma maliyetini ödersiniz ve tablo büyüdükçe daha da yavaşlar. Çözüm neredeyse her zaman anahtarlanmış bir Query'dir — erişim modelini bir anahtar etrafında tasarlayın, böylece DynamoDB her şey yerine tek bir partition'a dokunur.

  • Bir Scan tüm tabloyu okur, her seferinde. Ne ödediğine ve ne kadar sürdüğüne sonuç sayın değil, boyut karar verir.
  • FilterExpression maliyet hakkında bir yalandır. Okuma ölçüldükten sonra çalışır, bu yüzden 12 öğe döndürmek 12 milyon okuma için faturalandırabilir.
  • Bir Scan büyüdükçe yavaşlar. Anahtarlanmış bir Query düz kalır — tablo ne kadar büyürse büyüsün tek bir partition'a dokunur.
  • Düzeltme neredeyse her zaman ayar değil, modellemedir. Rutin bir soruya yanıt vermek için Scan yapıyorsan, bir anahtarı kaçırıyorsun.

Bir Scan gerçekte ne yapar

SQL'den gelince, SELECT * FROM events WHERE type = 'checkout' bedava gibi gelir — motorun bir index'i vardır ya da yoktur, ama her iki şekilde de satırları geri alırsın. DynamoDB'de bunu senin için karara bağlayan bir sorgu planlayıcı yoktur.

Bir Scan, tüm tabloyu sırayla, bir seferde 1 MB dolaşır ve her sayfayı FilterExpression'ına teslim eder. Filtrenin reddettiği her şey yine de okunur, yine de ölçülür ve yine de faturandadır. (AWS: Scanning tables)

İşte tuzak budur. Filtre bir WHERE cümlesine benzer, ama sonuç kümesini değiştirir, asla maliyeti değil. Bir Scan, bir filtre mevcut olsun ya da olmasın aynı okuma kapasitesini tüketir. (AWS: Scanning tables)

Okuma birimlerini say

DynamoDB okumaları okuma kapasite birimleri (RCU) ile ölçer. Bir RCU, 4 KB'ye kadar bir öğenin tek bir güçlü tutarlı okumasını satın alır; nihai tutarlı okumalar bunun yarısına mal olur. Daha büyük öğeler bir sonraki 4 KB'ye yuvarlanır. (AWS: Read/write capacity mode)

Bir analitik tablosu al, ProductEvents. Her satır izlenen bir etkinliktir:

PK  = "TENANT#acme"
SK  = "TS#2026-06-23T14:08:55Z#evt_9f3a"
attrs: eventType, sessionId, userId, payloadBytes

Diyelim ki 2.000.000 etkinlik tutuyor, her biri ~1 KB, hepsi tek bir yoğun tenant altında. Bugünün checkout'larını istiyorsun. Refleksif hamle:

Scan ProductEvents
FilterExpression: eventType = "checkout"

O filtre belki 40 satır döndürür. Ama Scan önce 2.000.000 öğenin hepsini okudu. Her biri ~1 KB'de (4 KB başına 1 RCU, nihai tutarlı ≈ 4 KB başına 0,5 RCU), 40 öğe geri vermek için kabaca 250.000 RCU ölçtün — ve ~500 MB veride sayfaladın.

Şimdi erişim desenini bir anahtar olarak modelle ve bunun yerine onu Query et:

Query ProductEvents
PK = "TENANT#acme"
AND SK begins_with "TS#2026-06-23"

Bu, tek bir partition'ın yalnızca eşleşen dilimini okur. O 40 checkout satırı artı günün diğer etkinlikleri ~2 MB'ye gelirse, 500 MB değil ~2 MB okuma için ödersin. Aynı cevap, maliyetin küçük bir kesri — ve tablo büyüdükçe gecikme düz kalır.

Scan ve Query, ölçülmüş

Scan + filtreAnahtarlanmış Query
OkumalarTablodaki her öğeBir partition, SK ile daraltılmış
Faturalanan kapasiteFiltreden önce tüm tabloYalnızca diliminizdeki öğeler
Örneğimiz~250.000 RCU (~500 MB)birkaç yüz RCU (~2 MB)
GecikmeTablo boyutuyla büyürTablo büyüdükçe düz
Sonuç sayısıMaliyet hakkında hiçbir şeye karar vermezNe ödediğinle eşleşir

Tablonun kodladığı ders: bir Scan'de, sonuç sayın ve faturan ilgisizdir. Bir Query'de, birbirlerini takip ederler.

Scan'den önce karar ver

Çoğu kazara Scan, tek bir sorudan gelir: ihtiyacım olan partition'ı adlandırabilir miyim? Evetse, bir Query'dir. Hayırsa, düzeltme daha büyük bir filtre değil, bir anahtardır.

İşte karar akış formunda.

EvetHayırEvetHayırÖğeleri okuma ihtiyacıPartition key biliniyor mu?Query bir partitionBir GSI anahtarlayabilir mi?Bir GSI ekle, sonra QueryScan son çare

Yol neredeyse her zaman Query'de biter; yalnızca hiçbir anahtar — mevcut ya da eklenebilir — erişim desenine uymadığında Scan'e düşersin.

Desen gerçek ve yinelenen ama temel tablo onu anahtarlayamıyorsa, bu, sorunun bir Query haline gelmesi için bir Global Secondary Index eklemenin sinyalidir. Anahtarlarını erişim desenlerinin etrafında en baştan modellemek tüm oyundur — bkz. single-table tasarım.

Bir filtre değil, anahtarlanmış sorguyu yaz

Anahtarın ötesinde bir koşula gerçekten ihtiyacın olduğunda, her şeyi bir FilterExpression'a boşaltmak yerine onu kasıtlı olarak oluştur. DynamoDB Expression Builder, senin için KeyConditionExpression'ı ve attribute placeholder'larını üretir, böylece partition ve sort key daraltmayı yapar — DynamoDB okumayı ölçmeden önce, sonra değil.

KeyConditionExpression: PK = :tenant AND begins_with(SK, :day)

Bir Scan gerçekten uygun olduğunda

Bir Scan yasak değildir — sadece yanlış varsayılandır. Gerçekten "her şeyi oku" demek istediğinde doğru araçtır:

  • Tek seferlik dışa aktarımlar veya elle çalıştırılan geri-doldurmalar (backfill).
  • Küçük yapılandırma / arama tabloları, tüm tablonun birkaç KB olduğu yerde.
  • Tüm tabloyu kasıtlı olarak sayfalayan arka plan işleri. Bunları, tek bir uzun sıralı tarama yerine Segment / TotalSegments ile işçiler arasında böl — bir paralel tarama. (AWS: Scanning tables)

Ve PartiQL'in seni kurtarmadığına dikkat et: anahtar yüklemi olmayan SELECT * FROM ProductEvents WHERE eventType = 'checkout', doğrudan bir Scan'e derlenir. SQL kılığındaki aynı ayak tuzağıdır. (Tam dökümü için bkz. Query ve Scan.)

Gerçekten öğeler arası analitiğe ihtiyacın olduğunda — bir GROUP BY, bir JOIN, DynamoDB'nin ifade edemeyeceği bir toplama (aggregate) — DynoTable'ın SQL Workbench'i bunları, tabloyu tam bir Scan ile dövmek yerine sınırlı bir sonuç kümesi üzerinde istemci tarafında çalıştırır.

Sonraki adımlar

Her iki desenin de ne kadara mal olacağını kapasite hesaplayıcısı ile tahmin et, API düzeyindeki karşıtlık için Query ve Scan'i oku ve bunları kendi tablolarına karşı çalıştırmak ve tüketilen kapasiteyi kendin görmek için DynoTable'ı indir.

Güncellendi