Orta6 dakikalık okuma

DynamoDB Seyrek İndeksler

seyrek endeksyalnızca kendi içeriğini taşıyan öğeleri tutan ikincil bir endekstir. temel özellik — böylece büyük bir tablonun küçük, sıcak bir alt kümesi kendine ait olur önceden filtrelenmiş, sorgulamaya hazır koleksiyon.

Milyonlarca satırınız var ama gün boyu çalıştırdığınız sorgu küçücük bir dilime dokunuyor: açık destek biletleri, ödenmemiş faturalar, incelenmek üzere işaretlenen hesaplar.

Bu dilimin filtrelenmesi yine de tüm tabloyu tarar ve her okuma için sizi faturalandırır. bir seyrek dizin bunun yerine endeksin kendisini küçük yapar.

DynamoDB'de seyrek indeks nedir?

Seyrek dizin, yalnızca anahtar niteliğini taşıyan öğeleri tutan ikincil bir dizindir. DynamoDB bu anahtarın eksik olduğu herhangi bir öğeyi atladığından, yalnızca istenen öğelerin (açık biletler, ödenmemiş faturalar) yazabileceği bir anahtar icat edersiniz ve endeks tam olarak bu alt küme haline gelir. Sorgular daha sonra sadece onu okur, filtre yoktur, okuma kapasitesi boşa gitmez.

  • İkincil dizin yalnızca kendi anahtarına sahip olan öğeleri dizine ekler.Anahtarı bir öğedir ve asla dizine girmez; yer tutucu yok, boş satır yok.
  • Yani sadece aranan eşyaların taşıyacağı bir anahtar icat ediyorsunuz.Bunu aldığınız eşyaların üzerine yazın sorguyu geri kalanından kaldırın. Endeks tam olarak bu alt küme haline gelir.
  • Sorgu yalnızca altkümeyi okur, filtre yoktur.Boyutu küçük sıcak kümeleri izler. tablo toplamı değil, ayarlayın.
  • REMOVE kaldıraçtır, boşluk bırakmaz.Boş bir dize geçerli bir dizin değildir tuşu — DynamoDB ValidationException ile yazma işleminin tamamını reddeder; niteliği silin.

Sorun: filtreleme okumaları kurtarmaz

SQL'den gelince, WHERE cümlesinin işi daralttığını varsayıyorsunuz. DynamoDB'lar FilterExpression öyle değil. Öğeler okunduktan sonraçalışır, önce değil.

Başına AWS Developer Guide, "Bir Sorgu, bir filtrenin olup olmadığına bakılmaksızın aynı miktarda okuma kapasitesi tüketir. ifadesi mevcut" - incelenen her öğe için ödeme yaparsın, ardından maç dışı deplasmanda.

Yani 5 milyon biletinizden 50'si açıksa, filtrelenmiş Query/Scan değeri okunur Milyonlarca kişi sana o 50'yi verecek.

Bu, her "taramam neden bu kadar pahalı" konusunun arkasındaki temel silahtır; query vs. scan tam maliyet resmine sahiptir.

Seyrek bir indeks, indeksin kendisini küçük yaparak onu atlatır.

Seyrekliğin nasıl çalıştığı

İkincil dizin yalnızca gerçekten dizinin anahtarına sahip olan öğeleri dizine ekler nitelikler.

AWS docs on sparse indexes şunu açıklayın: DynamoDB bir öğeyi yalnızca o öğe olduğunda ikincil dizine yazar endeksin temel özelliklerini taşır, dolayısıyla nadiren ayarlanan bir özelliğin üzerindeki dizin kalır doğal olarak küçüktür.

Bir öğede GSI'nin bölüm anahtarını (veya sıralama anahtarını) kaçırırsanız DynamoDB bunu yapmaz indekse yazın. Yer tutucu yok, boş satır yok; öğe yok.

Bütün mesele "varsayılan olarak yokluk"tur. status özelliğini indeksleme o every öğeyi taşır. Yalnızca istediğiniz öğeleri sağlayan bir özellik icat edin sorgu taşıma hiç .

Daha sonra endeks tam olarak bu öğelerin temiz bir listesi haline gelir ve buna karşı Query yalnızca bunları okur; filtre yok, kapasite kaybı yok.

Yalnızca anahtarı taşıyan öğelerin kesiştiği, dizini besleyen temel tabloyu hayal edin:

anahtar kaldırıldıanahtar kaldırıldıSeyrek GSI (yalnızca open)OpenOpenBase table (tüm item'lar)Open: anahtar varOpen: anahtar varClosed: anahtar yokClosed: anahtar yok

Yalnızca anahtarlı (açık) öğeler dizine çoğaltılır; kapalı eşyalar asla içine girmez.

Bu aynı anahtar şekillendirme zihniyetidir. single-table design: anahtarlar bir amaç için oluşturduğunuz araçlardır. verilerinizin aslına sadık yansımaları değil, belirli erişim düzeni.

İşlenmiş örnek: "yalnızca açık biletler"

Bir destek bileti masası alın. Temel tablo, kimliğe göre bilet almak için anahtarlanmıştır ve bir müşterinin biletlerini listelemek:

PKSKattributes
TICKET#a91fDETAILsubject, body, priority, openState
CUSTOMER#88TICKET#a91fsubject, priority, openState

Masanın ömrü boyunca çoğu bilet kapalıolur. Ancak kontrol paneli sorgusu temsilcilerinizin bütün gün vurduğu şey "önce en eskisi olmak üzere tüm açık biletleri bana gösterin" - birkaçı Milyonlarca satır arasında saklanan yüz satır.

openBucket bölüm anahtarı ve sıralama anahtarı ile tanımlayın openedAt ve açık biletlere yalnızca openBucket yazın. Ne zaman ayarlayın bilet oluşturulur; REMOVE bilet çözümlendiğinde.

PKSKopenBucketopenedAt
TICKET#a91fDETAILOPEN2026-06-23T09:14:00Z← open: in the index
TICKET#b02cDETAILOPEN2026-06-22T16:40:00Z← open: in the index
TICKET#77deDETAIL(absent)2026-05-30T11:02:00Z← closed: NOT in the index

a91f ve b02c biletleri openBucket taşıyor, yani GSI'da yaşıyorlar. Bilet 77de çözüldü ve openBucket kaldırıldı, dolayısıyla sessizce bırakıldı. gösterge tablosu artık ucuz bir sorgu:

Query  IndexName = "open-tickets-index"
KeyConditionExpression: openBucket = "OPEN"
ScanIndexForward: true        # oldest first

Bu yalnızca açık biletleri okur. Biletler kapandıkça endeks kendi kendine küçülüyor. sana open popülasyonunu izler, asla toplamı değil.

Bir statik bölüm değeri ("OPEN") burada tam olarak uygundur, çünkü set aynı kalır. küçük. Büyük bir açık kümenin parçalanmış bir bölüm anahtarına ihtiyacı olacaktır, ancak "küçük alt küme" index tam olarak bir değerin doğru çağrı olduğu yerdir.

İşe yarayan geçiş tek bir 'dir; Bilet çözümlendiğinde öznitelik.

REMOVE yan tümcesini ve okuma tarafı için yazılan anahtar koşulunu prototipleyin. DynamoDB Expression Builder yerine ExpressionAttributeNames ve :val yer tutucularını kendiniz elle monte edin.

Bunu DynoTable'da yapın

Seyrek indeksin en zor kısmı onu hangi öğelerin yaptığını görmektir sessizce düşen endekse girdi.

DynoTable tablo görünümünü ikincil bir dizine geçirmenizi ve tablo görünümünü tam olarak görmenizi sağlar. nüfuslu alt küme. Böylece çözümlenmiş bir biletin gerçekten kaldığını onaylayabilirsiniz open-tickets-index eski bir anahtarla oyalanmak yerine.

Açık biletler aracılığıyla görüntülenen destek bileti tablosu DynoTable'da GSI seyrektir ve yalnızca openBucket anahtarını taşıyan öğeleri gösterir.
Açık biletler aracılığıyla görüntülenen destek bileti tablosu DynoTable'da GSI seyrektir ve yalnızca openBucket anahtarını taşıyan öğeleri gösterir.
## Tuzaklar ve sonraki adımlar İzlenecek birkaç şey:
  • Anahtarı kaldırın, boş bırakmayın.Boş bir dize geçerli bir dizin anahtarı değildir — openBucket = "" yazmak ValidationException ile başarısız olur, bu nedenle öğe hiçbir zaman onunla indekslendi. Bir öğeyi dizinden çıkarmak için niteliği REMOVE yapmalısınız.
  • Dizin 'dir.GSI eşzamansız olarak güncellenir, dolayısıyla yeni çözümlenen bilet kısa süreliğine görünmeye devam edebilir — GSI okuma support eventual consistency only. "Bu bilet şu anda açık mı?" diye güvenmeyin.
  • Zihin nitelikleri.Dizindeki Query yalnızca ona yansıtılan nitelikler. Kontrol panelinin konu ve önceliğe ihtiyacı varsa, bunları yansıtın veya temel öğenin tamamı için fazladan GetItem ödeyin.
  • Hem GSI'ler hem de LSI'ler seyrek olabilir— kaldıraç aynıdır: endeksi atlayın Dizine eklenmesini istemediğiniz öğelere ilişkin sıralama anahtarı. GSI genellikle daha iyi uyum sağlar, yine de: tabloyu oluşturduktan sonra ekleyebilir ve ona kendi anahtar şemasını verebilirsiniz ve kapasite. GSI vs. LSI ödünleşimi bozar.

Seyrek indeksler modeldeki en eski fikirlerden biridir. Orijinal 2007 Amazon Dynamo paper Mağazayı bilinen, yüksek hacimli erişim kalıplarına ucuza hizmet verecek şekilde kurduk.

Seyrek dizin tam olarak şudur: anahtarları, ortak sorgunun hiçbir şey okumamasını sağlayacak şekilde şekillendirin ihtiyacı yok.

Gerçekte bir tane oluşturmak ve incelemek için, download DynoTable, onu doğrultun tablonuza gidin ve veri görünümünü seyrek GSI'nize çevirin — alt küme güncellemesini şu şekilde izleyin: öğeler indeks anahtarını kazanır ve kaybeder.

Güncellendi