İleri7 dakikalık okuma

Bir DynamoDB GSI Dahili Olarak Nasıl Saklanır

Bir Global Secondary Index, tablona geri dönen bir işaretçi değildir. O, DynamoDB'nin yazmaları içine asenkron olarak kopyalayarak senkronize tuttuğu ayrı, dahili olarak yönetilen bir tablodur — kendi partition'ları, kendi key şeması, kendi kapasitesi.

SQL'den geliyorsan, bir index aynı fiziksel tabloya cıvatalanmış, aynı transaction içinde güncellenen bir B-tree'dir. Bir GSI bu varsayımların ikisini de kırar ve neredeyse her GSI sürprizi tam da bu tek gerçeğe dayanır.

Bir DynamoDB GSI nasıl saklanır?

Bir DynamoDB GSI, base tabloya geri dönen bir işaretçi olarak değil, ayrı, dahili olarak yönetilen bir tablo olarak saklanır — kendi partition'ları, kendi key şeması ve kendi kapasitesiyle. DynamoDB her yazmayı index'e asenkron olarak kopyalar ve yalnızca GSI key'lerini, base tablo key'lerini ve varsa project edilen attribute'ları saklar.

  • Bir GSI kendi tablosudur. Base tablonunkiyle değil, GSI'nin partition key'iyle key'lenmiş, tamamen bağımsız bir partition uzayına sahiptir.
  • Yazmalar asenkron replike olur. Yazman önce base tabloya commit edilir, sonra DynamoDB onu bir arka plan yolu üzerinde her GSI'ye yelpazeler.
  • Yalnızca project edilen attribute'lar saklanır. Index, GSI key'lerini, base key'leri, artı project ettiğin attribute'ları tutar — başka bir şey değil.
  • GSI key'inin benzersiz olması gerekmez. Birden çok base item bir GSI partition/sort key'ini paylaşabilir; base birincil key, onları ayrı tutan belirleyicidir.

Tek bir base item'la başla

Bir SaaS denetim günlüğü ele al. Bir workspace'teki her ayrıcalıklı eylem, değişmez bir olay olur. Base tablo, WorkspaceEvents, bir workspace'in tüm olayları tek bir item koleksiyonunda, zamana göre sıralı yaşayacak şekilde key'lenmiştir:

WorkspaceEvents (base tablo)
EventPKEventSKactorIdverbtargetRef
WS#orbit-9TS#2026-06-23T14:02:11ZUSR#kpROLE_GRANTEDUSR#mara

EventPK = "WS#orbit-9" workspace'e göre partition'lar; EventSK bir ISO timestamp'tir, böylece bir Query bir workspace'in olaylarını kronolojik sırada döndürür. Bu, "bana bu workspace'in zaman çizelgesini göster"e mükemmel hizmet eder.

Başka hiçbir şeye hizmet etmez. "USR#kp her workspace'te ne yaptı?" diye soramazsın — actorId bir key değil, dolayısıyla onu base tabloda cevaplamanın tek yolu tam bir Scan'dir. Bir GSI'nin eklemek için var olduğu erişim deseni budur.

Bir GSI ekle ve ikinci bir tablonun belirmesini izle

Aynı olayları onları kimin gerçekleştirdiğine göre yeniden partition'layan bir GSI, ByActor, tanımla:

ByActor (GSI)
GSI1PK = actorId   ("USR#kp")
GSI1SK = EventSK   ("TS#2026-06-23T14:02:11Z")

DynamoDB artık ikinci bir fiziksel yapı tutar. Aynı mantıksal olay iki kez saklanır — bir kez base tablonun WS#orbit-9 partition'ında ve bir kez daha GSI'nin USR#kp partition'ında:

ByActor (GSI) — kendi partition uzayı
GSI1PKGSI1SKEventPKEventSKverb
USR#kpTS#2026-06-23T14:02:11ZWS#orbit-9TS#2026-06-23T14:02:11ZROLE_GRANTED

Neyin birlikte geldiğine dikkat et: base tablonun key'leri (EventPK, EventSK) her GSI item'ında otomatik olarak saklanır. Bir GSI isabetinin seni tam item'a geri işaret edebilmesinin — ve bir KEYS_ONLY index'in bile neden depolamaya mal olduğunun — nedeni budur.

GSI'de gerçekte ne yaşar

Index tüm item'ı kopyalamaz. Her GSI girdisi tam olarak üç şey tutar ve yalnızca üçüncüsünü kontrol edersin:

GSI'de saklananNereden gelirİsteğe bağlı?
GSI partition + sort keyGSI key'leri olarak adlandırdığın attribute'larHayır
Base tablo key('leri)Her base item'dan kopyalanırHayır
Project edilen attribute'larProjection seçiminEvet

Projection, KEYS_ONLY, INCLUDE (adlandırılmış bir liste) ya da ALL'dur. GSI üzerindeki bir Query yalnızca index'te olan attribute'ları döndürebilir.

Project edilmemiş birini iste ve DynamoDB onu şeffaf olarak getirmez — o alan için geriye hiçbir şey almazsın. (AWS GSI dokümanları)

İşte tersine çevrilmiş ilişkisel tuzak: SQL, eksik sütun için heap'e geri birleştirirdi. Bir GSI asla yapmaz. Projection tüm sözleşmedir.

Bir yazma index'e nasıl ulaşır

Replikasyon, SQL sezgisini en sert kıran kısımdır. Bir base yazması ve onun index güncellemesi tek bir atomik operasyon değildir.

PutItem yaptığında, DynamoDB dayanıklı olarak base tabloya commit eder, yazmanı onaylar ve sonra değişikliği her GSI'yi güncelleyen bir arka plan yoluna yayar. Onay, index'i beklemez.

İşte denetim yazmamız için olayların sırası, yukarıdan aşağıya:

PutItemWS#orbit-9 olayıBase partition'acommit etÇağırana200 OKAsync yol:GSI key'lerini çıkarByActor partitionUSR#kp'ye yönlendirProject edilenattribute'ları yaz

Çağıran, üçüncü adımda, dört ila altı adım bitmeden 200 OK'ini alır — dolayısıyla o aradaki ByActor üzerindeki bir Query, yepyeni bir olayı kaçırabilir.

O asenkronluk bir kusur değil, tasarım gereğidir: 2007 Amazon Dynamo makalesinin soyudur, ki o makale erişilebilirliği senkron tutarlılığa tercih etti. Tüm sonuçlar bir GSI'nin neden nihai tutarlı olduğunda yaşar.

GSI key'i benzersiz bir key değildir

SQL'de, benzersiz olmayan bir ikincil index varsayılandır ve benzersiz olan, kabul ettiğin bir kısıttır. Bir GSI bunun tersidir: hiçbir benzersizlik garantisi yoktur, asla.

Aynı aktörden, çakışan timestamp'lerdeki iki denetim olayı aynı GSI1PK ve GSI1SK'yı paylaşır. DynamoDB ikisini de saklar — onları her zaman taşınan base tablonun birincil key'iyle dahili olarak ayırt eder.

Yani bir aktör için bir anda bir GSI Query'si meşru olarak birkaç item döndürebilir. Bir SQL benzersiz index'inin sana vereceği şekilde key başına tek satır varsaydıysan, ayak kapanı budur.

Index'i sorguladığında, DynamoDB Expression Builder, KeyConditionExpression'ı name'ler ve value'lar doğru escape edilmiş olarak yazar — örn. bir kesim tarihinden beri bir aktörü eşleştirme:

KeyConditionExpression: "#a = :actor AND #ts > :since"
ExpressionAttributeNames:  { "#a": "actorId", "#ts": "EventSK" }
ExpressionAttributeValues: {
  ":actor": { "S": "USR#kp" },
  ":since": { "S": "TS#2026-06-01T00:00:00Z" }
}

Kapasite tabloyla değil, index'le yaşar

GSI kendi tablosu olduğundan, kendi okuma ve yazma kapasitesine sahiptir, base tablodan ayrı faturalandırılır ve kısıtlanır (throttle). ByActor'dan bir okuma, GSI'nin okuma birimlerini tüketir, asla tablonunkileri değil.

Isıran ters bağlantı şudur: her base-tablo yazması index'i de yazar ve GSI bunu ememezse, base yazmaya geri-basınç yapar. O mekanizma kendi kılavuzunu alır — bir GSI base-tablo yazmalarını ne zaman kısıtlar (throttle).

Bu ayrıca bir GSI'nin partition key'inin neden base tablonunki kadar önemli olduğudur. Düşük-kardinaliteli bir GSI key'i, base yazmalar mükemmel yayılmış olsa bile yazmaları tek bir index partition'ına kümeler — yeniden key'leyerek oluşturduğun bir hot partition.

Tuzaklar ve sonraki adımlar

  • Project edilmemiş attribute'ları geri bekleme. Bir GSI Query'si yalnızca index'in sakladığını döndürür. Tam item'a ihtiyacın varsa, onu project et ya da taşınan key'lerle base tablodan getir.
  • Bir GSI key'ini benzersiz olarak ele alma. Bir Query'nin key başına birden fazla item döndürmesini planla; base birincil key tek gerçek kimliktir.
  • Bir GSI'yi onu besleyen yazmadan hemen sonra okuma. Async yol, index'in yazmanı henüz göstermeyebileceği anlamına gelir — kendi yazmanı okumaya ihtiyacın olduğunda base tabloyu oku.
  • GSI'nin kapasitesini kasıtlı boyutlandır. Okumalarda bağımsız ve yazmalarda gizli bir bağımlılıktır.

Tüm oyun, desenlerine hizmet eden key şekilleri seçmektir — single-table design tek bir GSI'yi bunların birçoğu arasında aşırı yükler; GSI vs LSI ise yerel bir index'in bunun yerine ne zaman uyduğunu kapsar.

GSI KeyConditionExpression'ını DynamoDB Expression Builder içinde oluştur ve önizle, sonra bir index'in project edilen attribute'larını incelemek ve yazmaların kendi tablolarında GSI'ye replike olmasını izlemek için DynoTable'ı dene.

Güncellendi