Lanjutan7 menit baca

Pola Adjacency List DynamoDB

Sebuah graf hanyalah node dan edge, dan pola adjacency list menyimpan keduanya sebagai item biasa dalam satu tabel. Setiap edge menjadi sebuah baris yang partition key-nya adalah node sumber dan sort key-nya adalah targetnya. Meng-query sebuah partition mendaftarkan setiap tetangga — pengganti DynamoDB untuk sebuah JOIN pada tabel join.

Apa itu pola adjacency list DynamoDB?

Pola adjacency list memodelkan sebuah graf sebagai item edge dalam satu tabel: setiap relasi (A follow B) adalah sebuah baris yang ber-key sumber pada partition key dan target pada sort key. Meng-query sebuah partition mendaftarkan setiap tetangga, dan sebuah GSI terbalik membalik relasinya — tanpa join, tanpa scan, kedua arah dalam satu query.

  • Edge adalah item. Modelkan setiap relasi (user A follow user B) sebagai item-nya sendiri ber-key sumber pada partition key, target pada sort key.
  • Satu arah gratis; arah lainnya butuh GSI. Base table menjawab "siapa yang A follow?". Sebuah indeks terbalik menjawab "siapa yang follow A?".
  • Tanpa join, tanpa scan. Kedua arah adalah satu Query terhadap sebuah partition yang diketahui — tidak pernah sebuah Scan seluruh tabel.
  • Ia adalah primitif many-to-many. Follow, keanggotaan, like, pertemanan — graf apa pun di mana satu entitas terhubung ke banyak lainnya cocok dengan bentuk ini.

Bingkai sebagai pola akses

Datang dari SQL, sebuah graf follow adalah tabel join: follows(follower_id, followee_id). Untuk mendaftarkan follower seseorang Anda mengindeks satu kolom; untuk mendaftarkan siapa yang mereka follow Anda mengindeks kolom lainnya. DynamoDB tidak punya join, jadi Anda mendesain key-nya untuk melayani tiap pembacaan langsung.

Tuliskan pembacaannya lebih dulu. Untuk graf follow sosial:

  • Siapa yang user A follow? (daftar following mereka)
  • Siapa yang follow user A? (daftar followers mereka)
  • Apakah A follow B? (sebuah lookup titik tunggal)

Key-nya ada semata untuk menjawab daftar itu. Buat ia benar dan setiap pembacaan adalah satu Query atau GetItem.

Modelkan edge sebagai item

Gunakan nama key generik agar tabel bisa menampung lebih dari satu tipe entitas, dan encode tipe node di nilainya. Sebuah follow edge tampak seperti ini:

PKSKcreatedAtedgeType
ACTOR#aliceTARGET#bob1718900000FOLLOWS
ACTOR#aliceTARGET#carol1718900100FOLLOWS
ACTOR#daveTARGET#bob1718900200FOLLOWS

PK = ACTOR#alice adalah sumber edge; SK = TARGET#bob adalah siapa yang ia follow. Satu Query PK = "ACTOR#alice" mengembalikan setiap akun yang Alice follow dalam satu pembacaan yang ditagih — seluruh daftar following-nya, tanpa join.

Setiap edge ditulis sekali, dalam arah "siapa yang saya follow". Arah balik ("siapa yang follow saya") adalah bagian yang base table tak bisa jawab — belum.

Telusuri arah lainnya dengan GSI

Base table ber-key sumber-dulu, jadi ia tak bisa menjawab "siapa yang follow Bob?" tanpa scan. Tambahkan sebuah global secondary index yang membalik key-nya: proyeksikan target ke partition key indeks dan sumber ke sort key indeks.

GSI1PKGSI1SK(item base)
TARGET#bobACTOR#aliceACTOR#alice → TARGET#bob
TARGET#bobACTOR#daveACTOR#dave→ TARGET#bob
TARGET#carolACTOR#aliceACTOR#alice → TARGET#carol

Kini Query GSI1 WHERE GSI1PK = "TARGET#bob" mendaftarkan semua orang yang follow Bob — alice dan dave — dalam satu pembacaan. Item edge yang sama melayani kedua arah: base table adalah following, indeks adalah followers. Anda menulis setiap edge sekali dan mendapat kedua query gratis.

Base table: PK = ACTOR#aliceSK: TARGET#bobSK: TARGET#carolQuery base siapa yang alicefollow
GSI1: GSI1PK = TARGET#bobGSI1SK: ACTOR#aliceGSI1SK: ACTOR#daveQuery GSI1 siapa yang followbob

Ini persis pola yang AWS dokumentasikan dalam panduan best-practice DynamoDB-nya untuk memodelkan relasi many-to-many dan data graf — simpan edge sebagai item, lalu gunakan sebuah GSI untuk membalik relasinya.

Periksa satu edge dengan murah

"Apakah Alice follow Bob?" tidak butuh salah satu daftar. Karena edge-nya ber-key PK = ACTOR#alice, SK = TARGET#bob, itu adalah GetItem langsung — pembacaan termurah yang DynamoDB tawarkan, tanpa Query, tanpa indeks.

Untuk menulis follow secara idempoten dan menghindari penghitungan ganda, jaga PutItem dengan sebuah kondisi bahwa edge-nya belum ada:

attribute_not_exists(PK)

Anda bisa merakit kondisi itu — dan nilai key yang ter-marshal — dengan DynamoDB expression builder alih-alih menulis sendiri ConditionExpression dan ExpressionAttributeValues.

Lakukan di DynoTable

Saat Anda menjelajahi tabel, edge untuk satu actor menumpuk di bawah sebuah partition key sebagai satu item collection, dan beralih ke tampilan GSI menunjukkan daftar followers yang terbalik — dua paruh dari relasi berdampingan.

DynoTable menampilkan item follow-edge satu actor dalam satu partition, dengan atribut key GSI terlihat sebagai kolom.
DynoTable menampilkan item follow-edge satu actor dalam satu partition, dengan atribut key GSI terlihat sebagai kolom.

Jebakan

Partition selebritas. Seorang user dengan jutaan follower memusatkan setiap follower edge di bawah satu partition GSI1PK = TARGET#<star>. Pembacaan collection itu terpaginasi dan bisa berjalan panas. Untuk graf yang fan-out-heavy, shard hot key-nya (mis. TARGET#bob#0..N) atau denormalisasi penghitungan agar Anda tak perlu membaca ulang seluruh daftar.

Menyimpan penghitungan pada edge. Sebuah count follower bukanlah sebuah edge — jangan turunkan ia dengan membaca dan menghitung seluruh partition pada setiap tampilan profil. Pelihara sebuah atribut penghitung pada item user dan perbarui ia secara transaksional bersama edge-nya.

Lupa bahwa penulisan balik tidak dibutuhkan di sini. Sebuah varian adjacency-list klasik menulis edge dua kali dengan id ditukar. Dengan sebuah GSI flip-key Anda menulisnya sekali dan membiarkan indeks memmaterialisasi baliknya — lebih sedikit penulisan, tanpa penyimpangan antara dua salinan.

Langkah berikutnya

Adjacency list adalah balok bangunan relasi dari single-table design; indeks yang membalik adalah sebuah GSI, bukan LSI, karena partition key-nya berubah. Dan setiap pembacaan di sini adalah sebuah Query atau GetItem pada key yang diketahui — tidak pernah jebakan Scan.

Bangun ekspresi kondisi dan key dengan DynamoDB expression builder, dan unduh DynoTable untuk memodelkan graf follow terhadap tabel Anda sendiri dan amati kedua arah terselesaikan dalam satu pembacaan.

Diperbarui