Orta6 dakikalık okuma

DynamoDB'de Type Attribute

SQL'de bir satırın tablosu onun tipidir — documents içindeki bir satır bir belgedir. DynamoDB tek tablosu her entity'yi tek bir şema altında karıştırır, dolayısıyla bir item "bu nedir?" sorusuna yerleşik bir cevap taşımaz.

Type attribute'ı o cevabı geri koyar: her item üzerinde, temsil ettiği entity'yi adlandıran düz bir string.

DynamoDB'de Type attribute nedir?

Type attribute, her item'a damgaladığınız düz bir string'dir — örneğin EntityType: "Document" — temsil ettiği entity'yi adlandırır. Bir tek tablo, pek çok entity'yi tek bir şema altında karıştırdığından item'lar yerleşik bir tipe sahip değildir. Type bunu geri koyar; böylece kodunuz satırları tanımlar, bir GSI'yi tek bir entity'ye daraltır ve taşımalardan sağ çıkar.

  • Her yazmada bir Type damgala. Her item üzerinde tek bir attribute — EntityType: "Document" — istisnasız. Birkaç bayta mal olur ve sonradan seni kurtarır.
  • Karışık bir partition içinde entity'leri tanımlar. Bir Query workspace'leri, belgeleri ve yorumları bir arada döndürür; key prefix'lerini ayrıştırmadan hangisinin hangisi olduğunu Type kodun için söyler.
  • Bir GSI üzerinde tek entity filtrelemeyi besler. Type'ı bir index'e project et, böylece aşırı yüklü bir index'i tam olarak tek bir entity tipine daraltabilirsin.
  • Taşımalar için kaçış kapındır. Yeniden modellemek için export ettiğinde ya da bir entity'yi kendi tablosuna taşıdığında, Type üzerinden böldüğün sütundur.

Karışık bir tablo tipi neden kaybeder

Single-table design her entity'yi PK ve SK gibi genel key'lerin arkasında tek bir tabloda saklar. Bütün mesele bu — tek bir Query bir ebeveyni ve çocuklarını bir arada döndürür. Ama bu, bir partition'ın heterojen olduğu anlamına gelir.

Bir SaaS belge-iş birliği uygulamasını ele al. Bir workspace partition'ı workspace kaydını, belgelerini ve o belgelerdeki yorumları tutar:

PKSKattributes
WS#acmeMETAname, plan, seats
WS#acmeDOC#a1#METAtitle, owner, wordCount
WS#acmeDOC#a1#CMT#0007author, body, createdAt
WS#acmeDOC#a1#CMT#0008author, body, createdAt

Query PK = "WS#acme" dört item'ın tümünü tek bir faturalanan okumada geri verir. Şimdi kodun elinde ham item'ların bir listesi var ve hangisinin belge hangisinin yorum olduğunu söyleyecek güvenilir bir yolu yok — SK'yı string olarak eşleştirmek dışında, ki bu da key formatın değiştiği an kırılgan hale gelir.

Her item'a Type'ı damgala

Çözüm, her yazmada entity'yi adlandıran tek bir attribute:

PKSKEntityTypetitle
WS#acmeMETAWorkspace
WS#acmeDOC#a1#METADocumentQ3 Roadmap
WS#acmeDOC#a1#CMT#0007Comment

item.EntityType === "Document" üzerinden dallanmak kararlı bir eşitlik kontrolüdür. SK.startsWith("DOC#") && SK.includes("#CMT#") ayrıştırmak ise key'ini revize ettiğin an kırılan bir tahmindir. Type, okuma mantığını key kodlamandan ayırır — asıl kazanç budur.

Query PK = 'WS#acme'Karışık partitionEntityType: 'Workspace'EntityType: 'Document'EntityType: 'Comment'Type'a göre yönlendir

Tek bir okuma üç entity tipi döndürür; Type attribute'ı key'lere dokunmadan her item'ı doğru işleyiciye yönlendirir.

Bir GSI'yi tek bir entity'ye daralt

Type, index'lerde hak ettiğini kazanır. Diyelim ki "bu workspace'te son zamanlarda değişen her şeyi, en yenisi önce" listelemek için GSI1PK = WS#acme, GSI1SK = updatedAt üzerinde key'lenmiş bir GSI ekledin. Aşırı yüklü bir index belgeleri ve yorumları içeri süpürür — ama bir akış arayüzü yalnızca belgeleri isteyebilir.

Onu daraltmanın iki yolu var ve aradaki fark paradır:

YaklaşımMaliyetiNe zaman kullanılır
Type üzerinde FilterExpressionEşleşen tüm item'ları okur, hepsi için faturalandırır, eşleşmeyenleri okumadan sonra atarSonuçta karışık entity'ler nadir; hızlıca yola çıkmak için
Sparse index (GSI1PK'da Type)Yalnızca istediğin entity index'e inerTek bir entity baskınsa; sıfır israf istiyorsan

Bir FilterExpression item'lar okunduktan sonra ve kapasite tüketildikten sonra çalışır — AWS, filtrelemenin okuma maliyetini düşürmediğini açıkça belirtir (DynamoDB Developer Guide: FilterExpression). Type üzerinde filtreleme dürüsttür, bedava değil: attığın yorumlar için ödersin.

Akışı belgelere daraltmak için, sorgu Type attribute'ı üzerinde bir koşul taşır. FilterExpression'ı, name'leri ve value'ları DynamoDB expression builder ile birleştir — ayrılmış bir kelimeyi yanlış yazmaman için #t = :doc placeholder'ını üretir.

KeyConditionExpression     GSI1PK = :ws
FilterExpression           #t = :doc
ExpressionAttributeNames   { "#t": "EntityType" }
ExpressionAttributeValues  { ":ws": "WS#acme", ":doc": "Document" }

Index'in yalnızca belgeleri taşımasını ve filtreyi tamamen atlamasını mı istiyorsun? GSI1PK'yı yalnızca belge item'larına yaz — bir sparse index. GSI key'i olmayan item'lar asla index'e kopyalanmaz, dolayısıyla okuma yalnızca belgelere dokunur. Hangi item'ların uygun olduğunu yazara söyleyen şey Type attribute'ıdır.

Değeri kararlı ve tekil tut

Değeri bir kez seç ve onu bir enum gibi ele al. Document, asla bazen Doc bazen document değil — kayan bir değer, hiç değerin olmamasından daha kötüdür, çünkü eşitlik kontrollerin bir büyük/küçük harf yazımında geçer ve sessizce diğerini kaçırır.

Item başına tek Type. Bir item iki entity gibi hissettiriyorsa, bu genellikle bir modelleme kokusudur — tek bir satır iki şapka takmak yerine, her biri kendi koleksiyonunda ya da sort-key aralığında iki item olmalı.

Taşıma getirisi

Type'ı ihtiyacın olmadan önce damgalamanın nedeni: yeniden modelleme. Önerilen yeniden modelleme yolu export, dönüştür, yeniden import et — ve AWS tam da bu tür çevrimdışı yeniden şekillendirme için S3'e toplu export'u belgeler (DynamoDB'yi S3'e export etme).

O gün geldiğinde, Type GROUP BY yaptığın sütundur. Yorumları kendi tablolarına mı kaldırmak istiyorsun, yoksa export'u bir analitik warehouse için entity başına dosyalara mı yeniden normalleştirmek? Dökümü EntityType üzerinden bölersin. O olmadan, milyonlarca satır boyunca key'leri tersine mühendislik yapmaya geri dönersin.

Sonraki adımlar

Type attribute'ı ucuz bir sigortadır: karışık bir okumada entity'leri tanımla, aşırı yüklü bir GSI'yi filtrele ve yeniden modellediğinde temizce böl. İlk günden her yazmaya damgala — onu canlı bir tabloya sonradan eklemek tam bir geri doldurma demektir.

İlgili okumalar: bu attribute'ın hizmet ettiği karışık-partition deseni için single-table design, bir sparse index'in arkasındaki index şeklini seçmek için GSI vs LSI, ve bir FilterExpression'ın neden asla okuma maliyetinden kurtarmadığı için Query vs Scan.

Type üzerindeki filtreyi DynamoDB expression builder ile oluştur, ve gerçek bir karışık-entity tablosuna göz atıp Type sütununun her item boyunca hizalandığını görmek için DynoTable'ı dene.

Güncellendi