

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Pemodelan data untuk tabel DynamoDB
<a name="data-modeling"></a>

Sebelum kita menyelami pemodelan data, penting untuk memahami beberapa hal-hal dasar DynamoDB. DynamoDB adalah basis data NoSQL kunci-nilai yang memungkinkan skema fleksibel. Kumpulan atribut data selain atribut kunci untuk setiap item dapat berupa seragam atau diskrit. Skema kunci DynamoDB adalah dalam bentuk kunci primer sederhana di mana kunci partisi secara unik mengidentifikasi item, atau dalam bentuk kunci primer komposit di mana kombinasi kunci partisi dan kunci urutan secara unik mendefinisikan item. Kunci partisi di-hash untuk menentukan lokasi fisik data dan mengambilnya. Oleh karena itu, penting untuk memilih atribut dengan kardinalitas tinggi dan dapat diskalakan secara horizontal sebagai kunci partisi untuk memastikan distribusi data yang merata. Atribut kunci sortir adalah opsional dalam skema kunci dan memiliki kunci pengurutan memungkinkan pemodelan one-to-many hubungan dan membuat koleksi item di DynamoDB. Kunci urutan juga disebut sebagai kunci rentang, yang digunakan untuk mengurutkan item dalam koleksi item dan juga memungkinkan operasi berbasis rentang yang fleksibel.

Untuk detail selengkapnya dan praktik terbaik skema kunci DynamoDB, Anda dapat merujuk ke hal berikut:
+ [Partisi dan distribusi data di DynamoDB](HowItWorks.Partitions.md) 
+ [Praktik terbaik untuk merancang dan menggunakan kunci partisi secara efektif di DynamoDB](bp-partition-key-design.md) 
+ [Praktik terbaik untuk menggunakan kunci sortir untuk mengatur data di DynamoDB](bp-sort-keys.md) 
+ [Memilih kunci partisi DynamoDB yang tepat](https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/) 

Indeks sekunder kerap diperlukan untuk mendukung pola kueri tambahan di DynamoDB. Indeks sekunder adalah tabel bayangan tempat data yang sama diatur melalui skema kunci yang berbeda dibandingkan dengan tabel dasar. Indeks sekunder lokal (LSI) berbagi kunci partisi yang sama dengan tabel dasar dan memungkinkan untuk memiliki kunci urutan alternatif yang memungkinkan untuk berbagi kapasitas tabel dasar. Indeks sekunder global (GSI) dapat memiliki kunci partisi yang berbeda serta atribut kunci urutan yang berbeda dari tabel dasar, yang berarti manajemen throughput untuk GSI tidak tergantung pada tabel dasar.

Untuk detail selengkapnya tentang indeks sekunder dan praktik terbaik, Anda dapat merujuk ke hal berikut:
+ [Meningkatkan akses data dengan indeks sekunder di DynamoDB](SecondaryIndexes.md) 
+ [Praktik terbaik untuk menggunakan indeks sekunder di DynamoDB](bp-indexes.md) 

Sekarang mari kita lihat pemodelan data lebih dekat. Proses merancang skema yang fleksibel dan sangat dioptimalkan pada DynamoDB, atau basis data NoSQL apa pun dalam hal ini, dapat menjadi keterampilan yang menantang untuk dipelajari. Sasaran dari modul ini adalah untuk membantu Anda mengembangkan diagram alur mental untuk merancang skema yang akan membawa Anda dari kasus penggunaan ke produksi. Kita akan mulai dengan pengantar pilihan dasar dari desain apa pun, desain tabel tunggal versus desain multitabel. Kemudian, kita akan meninjau banyak pola desain (blok bangunan) yang dapat digunakan untuk mencapai berbagai hasil organisasi atau performa untuk aplikasi Anda. Terakhir, kita menyertakan berbagai paket desain skema lengkap untuk berbagai kasus penggunaan dan industri.

![\[Gambar menunjukkan hubungan konseptual antara data, blok yang berada di bawahnya, dan fondasi yang mendasari blok.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SchemaDesign.png)


**Topics**
+ [Koleksi item - cara memodelkan one-to-many hubungan di DynamoDB](WorkingWithItemCollections.md)
+ [Fondasi Pemodelan Data di DynamoDB](data-modeling-foundations.md)
+ [Blok bangunan pemodelan data di DynamoDB](data-modeling-blocks.md)
+ [Paket desain skema pemodelan data di DynamoDB](data-modeling-schemas.md)
+ [Praktik terbaik untuk memodelkan data relasional di DynamoDB](bp-relational-modeling.md)

# Koleksi item - cara memodelkan one-to-many hubungan di DynamoDB
<a name="WorkingWithItemCollections"></a>

Di DynamoDB, *koleksi item* adalah sekelompok item yang berbagi nilai kunci partisi yang sama, yang berarti item tersebut terkait. Koleksi item adalah mekanisme utama untuk memodelkan one-to-many hubungan di DynamoDB. Koleksi item hanya bisa ada pada tabel atau indeks yang dikonfigurasi untuk menggunakan [kunci primer komposit](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.PrimaryKey).

**catatan**  
Koleksi item bisa ada di tabel dasar atau indeks sekunder. Untuk informasi selengkapnya secara spesifik tentang bagaimana kumpulan item berinteraksi dengan indeks, lihat [Kumpulan item dalam Indeks Sekunder Lokal](LSI.md#LSI.ItemCollections).

Perhatikan tabel berikut yang menunjukkan tiga pengguna berbeda dan inventaris dalam game mereka:

![\[Tiga koleksi item yang berbeda dengan atribut yang berbeda.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/item_collection.png)


Untuk beberapa item di setiap koleksi, kunci urutan adalah gabungan informasi yang digunakan untuk mengelompokkan data, misalnya `inventory::armor`, `inventory::weapon`, atau `info`. Setiap koleksi item dapat memiliki kombinasi yang berbeda dari atribut ini sebagai kunci urutan. Pengguna `account1234` memiliki item `inventory::weapons`, sementara pengguna `account1387` tidak memilikinya (karena mereka belum menemukan apa pun). Pengguna `account1138` hanya menggunakan dua item untuk kunci urutan mereka (karena mereka belum memiliki inventaris) sedangkan pengguna lain menggunakan tiga item.

DynamoDB memungkinkan Anda secara selektif mengambil item dari koleksi item ini untuk melakukan hal berikut:
+ Mengambil semua item dari pengguna tertentu
+ Mengambil hanya satu item dari pengguna tertentu
+ Mengambil semua item dari jenis tertentu milik pengguna tertentu

## Mempercepat kueri dengan mengatur data Anda dengan koleksi item
<a name="WorkingWithItemCollections.Example"></a>

Dalam contoh ini, masing-masing item dalam tiga kumpulan item ini mewakili pemain dan model data yang telah kita pilih, berdasarkan pola akses game dan pemain. Data apa yang dibutuhkan game? Kapan game membutuhkannya? Seberapa sering game membutuhkannya? Berapa biaya untuk melakukannya dengan cara ini? Keputusan pemodelan data ini dibuat berdasarkan jawaban atas pertanyaan-pertanyaan ini.

Dalam game ini, ada halaman berbeda yang disajikan kepada pemain untuk inventaris senjata dan halaman lain untuk baju besi. Saat pemain membuka inventarisnya, senjata ditampilkan terlebih dahulu karena kami ingin halaman tersebut dimuat dengan sangat cepat, sedangkan halaman inventaris berikutnya dapat dimuat setelahnya. Karena masing-masing jenis item ini bisa berukuran cukup besar seiring pemain memperoleh lebih banyak item dalam game, kami memutuskan bahwa setiap halaman inventaris akan menjadi itemnya sendiri dalam koleksi item pemain di basis data. 

Bagian berikut membahas lebih lanjut tentang bagaimana Anda dapat berinteraksi dengan koleksi item melalui operasi `Query`.

**Topics**
+ [Mempercepat kueri dengan mengatur data Anda dengan koleksi item](#WorkingWithItemCollections.Example)

# Fondasi Pemodelan Data di DynamoDB
<a name="data-modeling-foundations"></a>

Bagian ini mencakup lapisan fondasi dengan memeriksa dua jenis desain tabel: tabel tunggal dan multitabel.

![\[Gambar menunjukkan hubungan konseptual antara data, blok yang berada di bawahnya, dan fondasi yang mendasari blok. Penekanan pada fondasi.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SchemaDesignFoundation.png)


## Fondasi desain tabel tunggal
<a name="data-modeling-foundations-single"></a>

Salah satu pilihan untuk fondasi skema DynamoDB adalah **desain tabel tunggal**. Desain tabel tunggal adalah pola yang memungkinkan Anda menyimpan beberapa jenis (entitas) data dalam tabel DynamoDB tunggal. Hal ini bertujuan untuk mengoptimalkan pola akses data, meningkatkan performa, dan mengurangi biaya dengan menghilangkan kebutuhan untuk memelihara beberapa tabel dan hubungan yang kompleks di antara tabel-tabel tersebut. Hal ini dimungkinkan karena DynamoDB menyimpan item dengan kunci partisi yang sama (dikenal sebagai koleksi item) pada partisi yang sama satu sama lain. Dalam desain ini, berbagai jenis data disimpan sebagai item dalam tabel yang sama, dan setiap item diidentifikasi dengan kunci urutan yang unik.

![\[Gambar menampilkan tabel dan bagaimana kunci urutan digunakan untuk membedakan setiap item berdasarkan jenis entitas dalam koleksi UserID Item yang sama.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SingleTableSchema.png)


**Keuntungan**
+ Lokalitas data untuk mendukung kueri untuk beberapa jenis entitas dalam satu panggilan basis data
+ Mengurangi biaya keuangan dan latensi pembacaan secara keseluruhan:
  + Satu kueri untuk dua item dengan total kurang dari 4KB adalah 0,5 RCU yang pada akhirnya konsisten
  + Dua kueri untuk dua item dengan total kurang dari 4KB adalah 1 RCU yang pada akhirnya konsisten (masing-masing 0,5 RCU)
  + Waktu untuk mengembalikan dua panggilan database terpisah akan rata-rata lebih tinggi dari satu panggilan
+ Mengurangi jumlah tabel untuk dikelola:
  + Izin tidak perlu dipertahankan di beberapa kebijakan atau peran IAM 
  + Manajemen kapasitas untuk tabel dirata-ratakan di seluruh entitas, biasanya menghasilkan pola konsumsi yang lebih dapat diprediksi
  + Pemantauan membutuhkan alarm yang lebih sedikit
  + Kunci Enkripsi yang Dikelola Pelanggan hanya perlu dirotasi pada satu tabel
+ Memperlancar lalu lintas ke tabel:
  + Dengan menggabungkan beberapa pola penggunaan ke tabel yang sama, penggunaan secara keseluruhan cenderung lebih lancar (seperti performa indeks saham yang cenderung lebih lancar dibandingkan dengan saham individual) yang bekerja lebih baik untuk mencapai penggunaan yang lebih tinggi dengan tabel mode yang telah disediakan

**Kekurangan**
+ Kurva pembelajaran bisa curam karena desain paradoks dibandingkan dengan basis data relasional
+ Persyaratan data harus konsisten di semua jenis entitas
  + Pencadangan semuanya atau tidak sama sekali jadi jika beberapa data tidak penting untuk misi, pertimbangkan untuk menyimpannya di tabel terpisah
  + Enkripsi tabel dibagikan di semua item. Untuk aplikasi multi-penghuni dengan persyaratan enkripsi penghuni individual, enkripsi di sisi klien akan diperlukan
  + Tabel dengan campuran data historis dan data operasional tidak akan mendapatkan banyak manfaat dengan mengaktifkan Kelas Penyimpanan Akses Jarang. Untuk informasi selengkapnya, lihat [Kelas tabel DynamoDB](HowItWorks.TableClasses.md) 
+ Semua data yang diubah akan disebarkan ke DynamoDB Streams meskipun hanya sebagian dari entitas yang perlu diproses.
  + Berkat filter peristiwa Lambda, hal ini tidak akan memengaruhi tagihan Anda saat menggunakan Lambda, tetapi akan menjadi biaya tambahan saat menggunakan Kinesis Consumer Library 
+ Saat menggunakan GraphQL, desain tabel tunggal akan lebih sulit diterapkan
+ Saat menggunakan klien SDK tingkat tinggi seperti [`DynamoDBMapper`](DynamoDBMapper.md) Java atau [Enhanced Client](DynamoDBEnhanced.md), akan lebih sulit untuk memproses hasil karena item dalam respons yang sama dapat dikaitkan dengan kelas yang berbeda

**Kapan harus digunakan**

Desain tabel tunggal bekerja dengan baik untuk aplikasi yang sering menanyakan beberapa jenis entitas bersama-sama atau perlu mempertahankan hubungan antara tipe data yang berbeda. Ini sangat efektif ketika pola akses Anda mendapat manfaat dari lokalitas data dan ketika Anda ingin meminimalkan overhead mengelola beberapa tabel.

## Fondasi desain multitabel
<a name="data-modeling-foundations-multi"></a>

Pilihan kedua untuk fondasi skema DynamoDB kita adalah desain multitabel****. Desain multitabel adalah pola yang lebih mirip dengan desain basis data tradisional tempat Anda menyimpan satu jenis (entitas) data dalam setiap tabel DynamoDB. Data dalam setiap tabel tetap akan diatur oleh kunci partisi, sehingga performa dalam satu jenis entitas akan dioptimalkan untuk skalabilitas dan performa, tetapi kueri di beberapa tabel harus dilakukan secara independen.

![\[Gambar menunjukkan tabel forum yang berisi daftar forum dan beberapa data agregat.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/MultipleTable1.png)


![\[Gambar yang menunjukkan tabel thread yang berisi daftar thread yang dipartisi oleh forum tertentu tempatnya berada.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/MultipleTable2.png)


**Keuntungan**
+ Perancangannya lebih sederhana bagi mereka yang tidak terbiasa bekerja dengan desain tabel tunggal 
+ Implementasi resolver GraphQL yang lebih mudah karena setiap resolver dipetakan ke satu entitas (tabel)
+ Memungkinkan persyaratan data unik di berbagai jenis entitas:
  + Cadangan dapat dibuat untuk tabel individu yang sangat penting untuk misi 
  + Enkripsi tabel dapat dikelola untuk setiap tabel. Untuk aplikasi multi-penghuni dengan persyaratan enkripsi penghuni individual, tabel penghuni terpisah memungkinkan setiap pelanggan memiliki kunci enkripsinya sendiri
  + Kelas Penyimpanan Akses Jarang dapat diaktifkan hanya pada tabel dengan data historis untuk merealisasikan manfaat penghematan biaya penuh. Untuk informasi selengkapnya, lihat [Kelas tabel DynamoDB](HowItWorks.TableClasses.md)
+ Setiap tabel akan memiliki aliran data perubahannya sendiri yang memungkinkan fungsi Lambda khusus dirancang untuk setiap jenis item daripada prosesor monolitik tunggal

**Kekurangan**
+ Untuk pola akses yang memerlukan data di beberapa tabel, beberapa pembacaan dari DynamoDB akan diperlukan dan data processed/joined mungkin perlu ada pada kode klien.
+ Operasi dan pemantauan beberapa tabel membutuhkan lebih banyak CloudWatch alarm dan setiap tabel harus diskalakan secara independen
+ Setiap izin tabel perlu dikelola secara terpisah. Penambahan tabel nantinya akan memerlukan perubahan pada kebijakan atau peran IAM yang diperlukan

**Kapan harus digunakan**

Jika pola akses aplikasi Anda tidak memiliki kebutuhan untuk melakukan kueri untuk beberapa entitas atau tabel bersama-sama, maka desain multitabel adalah pendekatan yang baik dan memadai.

# Blok bangunan pemodelan data di DynamoDB
<a name="data-modeling-blocks"></a>

Bagian ini membahas lapisan blok bangunan yang dapat Anda gunakan dalam pola deasin untuk aplikasi Anda.

![\[Gambar menunjukkan hubungan konseptual antara data, blok yang berada di bawahnya, dan fondasi yang mendasari blok. Penekanan pada fondasi.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SchemaDesignBlocks.png)


**Topics**
+ [Blok bangunan kunci urutan komposit](#data-modeling-blocks-composite)
+ [Blok bangunan multi-penghunian](#data-modeling-blocks-multi-tenancy)
+ [Blok bangunan indeks jarang](#data-modeling-blocks-sparse-index)
+ [Blok bangunan waktu untuk tayang](#data-modeling-blocks-ttl)
+ [Blok bangunan pengarsipan waktu untuk tayang](#data-modeling-blocks-ttl-archival)
+ [Blok bangunan partisi vertikal](#data-modeling-blocks-vertical-partitioning)
+ [Blok bangunan sharding penulisan](#data-modeling-blocks-write-sharding)

## Blok bangunan kunci urutan komposit
<a name="data-modeling-blocks-composite"></a>

Bicara tentang NoSQL, orang-orang mungkin juga menganggapnya sebagai non-relasional. Pada akhirnya, tidak ada hal yang menghalangi relasi untuk ditempatkan ke dalam skema DynamoDB, meski tampilannya berbeda dari basis data relasional dan kunci asingnya. Salah satu pola paling kritis yang dapat kita gunakan untuk mengembangkan hierarki logis data kita di DynamoDB adalah kunci urutan komposit. Gaya yang paling umum untuk merancangnya adalah dengan memisahkan setiap lapisan hierarki (layer induk > lapisan turunan > lapisan cucu) dengan tagar. Misalnya, `PARENT#CHILD#GRANDCHILD#ETC`.

![\[Gambar yang menampilkan item dalam tabel dengan userID sebagai kunci primer, dan kombinasi atribut lainnya sebagai kunci urutan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ShoppingCart.png)


Sementara kunci partisi di DynamoDB selalu membutuhkan nilai yang tepat untuk kueri data, kita dapat menerapkan kondisi parsial ke kunci urutan dari kiri ke kanan, mirip dengan melintasi pohon biner.

Dalam contoh di atas, ada toko e-Commerce dengan Keranjang Belanja yang perlu dipertahankan di seluruh sesi pengguna. Setiap kali pengguna masuk, mereka mungkin ingin melihat seluruh Keranjang Belanja, termasuk item yang disimpan untuk nanti. Namun ketika mereka memasuki halaman checkout, hanya item di keranjang aktif yang harus dimuat untuk dibeli. Karena kedua `KeyConditions` ini secara eksplisit meminta kunci urutan CART, data daftar keinginan tambahan diabaikan begitu saja oleh DynamoDB pada waktu baca. Meskipun item yang disimpan dan aktif adalah bagian dari keranjang yang sama, kita perlu memperlakukannya secara berbeda di berbagai bagian aplikasi, jadi menerapkan `KeyCondition` ke prefiks kunci urutan adalah cara yang paling optimal untuk hanya mengambil data yang diperlukan untuk setiap bagian aplikasi.

**Fitur utama dari blok bangunan ini**
+ Item terkait disimpan secara lokal satu sama lain untuk akses data yang efektif 
+ Menggunakan `KeyCondition` ekspresi, himpunan bagian dari hierarki dapat diambil secara selektif yang berarti tidak ada yang sia-sia RCUs 
+ Bagian yang berbeda dari aplikasi dapat menyimpan item-nya di bawah prefiks tertentu, yang mencegah penimpaan item atau penulisan yang bertentangan

## Blok bangunan multi-penghunian
<a name="data-modeling-blocks-multi-tenancy"></a>

Banyak pelanggan menggunakan DynamoDB sebagai host data untuk aplikasi multi-penghuni mereka. Untuk skenario ini, kami ingin merancang skema dengan cara yang menyimpan semua data dari penghuni tunggal di partisi logisnya sendiri dari tabel. Hal ini memanfaatkan konsep Koleksi Item, yang merupakan istilah untuk semua item dalam tabel DynamoDB dengan kunci partisi yang sama. [Untuk informasi selengkapnya tentang cara pendekatan DynamoDB terhadap multi-penghuni, lihat Multi-penghuni di DynamoDB](https://docs.aws.amazon.com/whitepapers/latest/multi-tenant-saas-storage-strategies/multitenancy-on-dynamodb.html). 

![\[Gambar menunjukkan tabel yang dapat mewakili situs foto multi-penghuni. Kunci primer terdiri dari pengguna sebagai kunci partisi dan foto yang berbeda sebagai kunci urutan. Atribut untuk setiap item menunjukkan URL tempat foto di-host.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/MultiTenant.png)


Untuk contoh ini, kami menjalankan situs hosting foto dengan potensi ribuan pengguna. Setiap pengguna hanya akan mengunggah foto ke profil mereka sendiri pada awalnya, tetapi secara default kami tidak akan mengizinkan pengguna untuk melihat foto pengguna lain. Tingkat isolasi tambahan idealnya akan ditambahkan ke otorisasi panggilan setiap pengguna ke API Anda untuk memastikan mereka hanya meminta data dari partisi mereka sendiri, tetapi pada tingkat skema, kunci partisi unik sudah cukup.

**Fitur utama dari blok bangunan ini**
+ Jumlah data yang dibaca oleh satu pengguna atau penghuni hanya bisa sebanyak jumlah total item di partisi mereka
+ Penghapusan data penghuni karena penutupan akun atau permintaan kepatuhan dapat dilakukan dengan taktis dan murah. Cukup jalankan kueri di mana kunci partisi sama dengan ID penyewanya, lalu jalankan operasi `DeleteItem` untuk setiap kunci primer yang dikembalikan

**catatan**  
Dirancang dengan mempertimbangkan multi-tenancy, Anda dapat menggunakan penyedia kunci enkripsi yang berbeda di satu tabel untuk mengisolasi data dengan aman. [AWS SDK Enkripsi Basis Data](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/what-is-database-encryption-sdk.html) untuk Amazon DynamoDB memungkinkan Anda menyertakan enkripsi di sisi klien dalam beban kerja DynamoDB Anda. Anda dapat melakukan enkripsi tingkat atribut, memungkinkan Anda mengenkripsi nilai atribut tertentu sebelum menyimpannya di tabel DynamoDB Anda dan mencari atribut terenkripsi tanpa mendekripsi seluruh basis data sebelumnya. 

## Blok bangunan indeks jarang
<a name="data-modeling-blocks-sparse-index"></a>

Terkadang pola akses memerlukan pencarian item yang cocok dengan item langka atau item yang menerima status (yang memerlukan respons yang dieskalasikan). Daripada melakukan kueri secara reguler di seluruh set data untuk item-item ini, kita dapat memanfaatkan fakta bahwa **indeks sekunder global (GSI)** jarang dimuat dengan data. Ini berarti bahwa hanya item dalam tabel dasar yang memiliki atribut yang ditentukan dalam indeks yang akan direplikasi ke indeks.

![\[Gambar yang menunjukkan tabel dasar yang menerima sejumlah besar data dalam kondisi stabil\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SparseBaseTable.png)


![\[Gambar yang menunjukkan indeks sekunder global yang hanya menerima item yang telah dieskalasi\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SparseGSI.png)


Dalam contoh ini, kita melihat kasus penggunaan IOT di mana setiap perangkat di lapangan melaporkan kembali status secara reguler. Untuk sebagian besar laporan, kita berharap perangkat melaporkan semuanya baik-baik saja, tetapi kadang-kadang kesalahan bisa saja muncul, dan hal itu harus dieskalasikan ke teknisi perbaikan. Untuk laporan dengan eskalasi, atribut `EscalatedTo` ditambahkan item, tetapi malah tidak muncul. GSI dalam contoh ini dipartisi oleh `EscalatedTo`, dan karena GSI membawa kunci dari tabel dasar, kita masih dapat melihat DeviceID yang melaporkan kesalahan dan pada pukul berapa.

Meskipun pembacaan lebih murah daripada penulisan di DynamoDB, indeks jarang adalah alat yang sangat efektif untuk kasus penggunaan di mana instans jenis item tertentu jarang terjadi tetapi pembacaan untuk menemukannya merupakan hal biasa.

**Fitur utama dari blok bangunan ini**
+ Biaya tulis dan penyimpanan untuk GSI jarang hanya berlaku untuk item yang cocok dengan pola kunci, sehingga biaya GSI bisa jauh lebih rendah daripada yang lain yang memiliki semua item GSIs yang direplikasi ke mereka 
+ Kunci urutan komposit masih dapat digunakan untuk menyaring item yang cocok dengan kueri yang diinginkan, misalnya, stempel waktu dapat digunakan untuk kunci urutan agar hanya melihat kesalahan yang dilaporkan dalam X menit terakhir (`SK > 5 minutes ago, ScanIndexForward: False`)

## Blok bangunan waktu untuk tayang
<a name="data-modeling-blocks-ttl"></a>

Sebagian besar data memiliki beberapa durasi waktu yang dapat dianggap layak disimpan dalam penyimpanan data primer. Untuk memfasilitasi penuaan data dari DynamoDB, ada fitur yang disebut **waktu untuk tayang (TTL)**. Fitur [TTL](TTL.md) memungkinkan Anda untuk menentukan atribut tertentu pada tingkat tabel yang memerlukan pemantauan untuk item dengan stempel waktu epoch (itu di masa lalu). Hal ini memungkinkan Anda untuk menghapus catatan kedaluwarsa dari tabel secara gratis.

**catatan**  
Jika Anda menggunakan [Global Tables versi 2019.11.21 (Saat ini)](GlobalTables.md) dari tabel global dan Anda juga menggunakan fitur [Time to Live](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html), DynamoDB mereplikasi penghapusan TTL ke semua tabel replika. Penghapusan TTL awal tidak mengonsumsi kapasitas tulis di wilayah tempat TTL kedaluwarsa. Namun, penghapusan TTL yang direplikasi untuk tabel replika mengonsumsi unit kapasitas tulis yang direplikasi ketika menggunakan kapasitas di setiap Wilayah replika dan biaya akan berlaku.

![\[Gambar yang menampilkan tabel dengan pesan pengguna dengan atribut waktu untuk beroperasi\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/TTL.png)


Dalam contoh ini, kami memiliki aplikasi yang dirancang untuk memungkinkan pengguna membuat pesan berumur pendek. Ketika pesan dibuat di DynamoDB, atribut TTL diatur ke tanggal tujuh hari di masa depan oleh kode aplikasi. Dalam kira-kira tujuh hari, DynamoDB akan melihat bahwa stempel jangka waktu item ini sudah ada di masa lalu kemudian menghapusnya.

Karena penghapusan yang dilakukan oleh TTL gratis, sangat disarankan untuk menggunakan fitur ini guna menghapus data historis dari tabel. Ini akan mengurangi tagihan penyimpanan keseluruhan setiap bulan dan kemungkinan akan mengurangi biaya pembacaan pengguna karena data yang akan diambil oleh kueri mereka menjadi lebih sedikit. Meskipun TTL diaktifkan pada tingkat tabel, Anda bebas menentukan item atau entitas mana yang akan membuat atribut TTL dan seberapa jauh stempel jangka waktu diatur ke depannya.

**Fitur utama dari blok bangunan ini**
+ Penghapusan TTL dijalankan di belakang layar tanpa berdampak pada performa tabel Anda 
+ TTL adalah proses asinkron yang berjalan kira-kira setiap enam jam, tetapi penghapusan catatan kedaluwarsa dapat memakan waktu lebih dari 48 jam 
  + Jangan mengandalkan penghapusan TTL untuk kasus penggunaan seperti catatan kunci atau manajemen status jika data basi harus dibersihkan dalam waktu kurang dari 48 jam 
+ Anda dapat memberi atribut TTL dengan nama atribut yang valid, tetapi nilainya harus berupa jenis angka

## Blok bangunan pengarsipan waktu untuk tayang
<a name="data-modeling-blocks-ttl-archival"></a>

Meski TTL adalah alat yang efektif untuk menghapus data lama dari DynamoDB, banyak kasus penggunaan mewajibkan arsip data disimpan untuk jangka waktu yang lebih lama dibandingkan penyimpanan data primer. Dalam instans, kita dapat memanfaatkan penghapusan catatan berwaktu TTL untuk mendorong catatan kedaluwarsa ke dalam penyimpanan data jangka panjang.

![\[Gambar menunjukkan tabel yang mengirimkan tugas penghapusan waktu untuk beroperasi ke Aliran DynamoDB yang diikuti oleh penyimpanan data jangka panjang.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/TTLArchive.png)


Ketika penghapusan TTL dilakukan oleh DynamoDB, TTL masih didorong ke Aliran DynamoDB sebagai peristiwa `Delete`. Ketika penghapusan dilakukan oleh TTL DynamoDB, ada atribut pada catatan aliran `principal:dynamodb`. Menggunakan pelanggan Lambda ke DynamoDB Stream, kita dapat menerapkan filter peristiwa hanya untuk atribut utama DynamoDB dan mengetahui bahwa catatan apa pun yang cocok dengan filter tersebut akan didorong ke penyimpanan arsip seperti Amazon Glacier.

**Fitur utama dari blok bangunan ini**
+  Setelah pembacaan DynamoDB latensi rendah tidak lagi diperlukan untuk item historis, memigrasikannya ke layanan penyimpanan yang lebih dingin seperti Amazon Glacier dapat mengurangi biaya penyimpanan secara signifikan sekaligus memenuhi kebutuhan kepatuhan data dari kasus penggunaan Anda 
+ Jika data disimpan di Amazon S3, alat analitik hemat biaya seperti Amazon Athena atau Redshift Spectrum dapat digunakan untuk melakukan analisis historis data

## Blok bangunan partisi vertikal
<a name="data-modeling-blocks-vertical-partitioning"></a>

Pengguna yang sudah familier dengan basis data model dokumen juga akan familier dengan gagasan menyimpan semua data terkait dalam satu dokumen JSON. Sementara DynamoDB mendukung tipe data JSON, itu tidak mendukung `KeyConditions` eksekusi pada JSON bersarang. Karena itulah `KeyConditions` yang menentukan berapa banyak data yang dibaca dari disk dan secara efektif berapa banyak kueri RCUs yang dikonsumsi, ini dapat mengakibatkan inefisiensi pada skala. Untuk mengoptimalkan penulisan dan pembacaan DynamoDB dengan lebih baik, kami sarankan untuk memecah entitas individual dokumen menjadi item DynamoDB individual, yang juga disebut sebagai **partisi vertikal**.

![\[Gambar yang menunjukkan struktur data besar diformat sebagai objek JSON tertanam.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DocumentBlob.png)


![\[Gambar yang menunjukkan koleksi item di mana kunci urutan item membantu menjaga optimalnya penggunaan DynamoDB.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SingleTableSchema.png)


Partisi vertikal, seperti yang ditunjukkan di atas, adalah contoh kunci desain tabel tunggal dalam kenyataannya, tetapi juga dapat diimplementasikan di beberapa tabel jika diinginkan. Karena tagihan DynamoDB menulis dalam kelipatan 1 KB, Anda idealnya harus mempartisi dokumen dengan cara yang menghasilkan item di bawah 1 KB.

**Fitur utama dari blok bangunan ini**
+ Hierarki hubungan data dipertahankan melalui prefiks kunci urutan agar struktur dokumen tunggal dapat dibangun kembali sisi klien jika diperlukan 
+ Komponen tunggal dari struktur data dapat diperbarui secara independen, sehingga item kecil dapat diperbarui meski hanya 1 WCU 
+ Dengan menggunakan kunci urutan `BeginsWith`, aplikasi dapat mengambil data serupa dalam satu kueri, yang menggabungkan biaya baca untuk mengurangi total biaya/latensi
+ Dokumen besar bisa saja lebih besar dari batas ukuran item individu 400 KB di DynamoDB dan partisi vertikal membantu mengatasi batas ini

## Blok bangunan sharding penulisan
<a name="data-modeling-blocks-write-sharding"></a>

Salah satu dari sedikit batasan keras yang dimiliki DynamoDB adalah pembatasan jumlah throughput yang dapat dipertahankan oleh satu partisi fisik per detik (tidak harus satu kunci partisi). Batasan ini untuk saat ini:
+ 1000 WCU (atau 1000 <= 1 KB item ditulis per detik) dan 3000 RCU (atau 3000 <= 4 KB dibaca per detik) *sangat konsisten* atau 
+ 6000 <=4 KB dibaca per detik *pada akhirnya konsisten*

Jika permintaan terhadap tabel melebihi salah satu dari batas ini, kesalahan dikirim kembali ke SDK klien `ThroughputExceededException`, yang umumnya disebut sebagai throttling. Kasus penggunaan yang memerlukan operasi baca di luar batas itu sebagian besar akan dilayani paling baik dengan menempatkan cache baca di depan DynamoDB, tetapi operasi penulisan memerlukan desain tingkat skema yang dikenal sebagai **sharding penulisan**.

![\[Gambar yang menunjukkan bagaimana DynamoDB memecah kunci partisi di beberapa partisi untuk mencegah throttling dari lonjakan lalu lintas.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/WriteShardingProblem.png)


![\[Gambar yang menunjukkan bagaimana DynamoDB memecah kunci partisi di beberapa partisi untuk mencegah throttling dari lonjakan lalu lintas.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/WriteShardingSolution.png)


Untuk mengatasi masalah ini, kita akan menambahkan bilangan bulat acak ke akhir kunci partisi untuk setiap kontestan dalam kode `UpdateItem` aplikasi. Rentang generator bilangan bulat acak harus memiliki pencocokan batas atas atau melebihi jumlah penulisan per detik yang diharapkan untuk kontestan tertentu dibagi 1000. Untuk mendukung 20.000 suara per detik, hal ini akan terlihat seperti rand(0,19). Setelah data disimpan di bawah partisi logis yang terpisah, data harus digabungkan bersama kembali pada waktu baca. Karena total suara tidak perlu real time, fungsi Lambda yang dijadwalkan untuk membaca semua partisi suara setiap X menit dapat melakukan agregasi sesekali untuk setiap kontestan dan menuliskannya kembali ke catatan total suara tunggal untuk pembacaan langsung.

**Fitur utama dari blok bangunan ini**
+ Untuk kasus penggunaan dengan throughput tulis yang sangat tinggi untuk kunci partisi tertentu yang tidak dapat dihindari, operasi tulis dapat tersebar secara artifisial di beberapa partisi DynamoDB 
+ GSIs dengan kunci partisi kardinalitas rendah juga harus menggunakan pola ini karena pelambatan pada GSI akan menerapkan tekanan balik untuk menulis operasi pada tabel dasar

# Paket desain skema pemodelan data di DynamoDB
<a name="data-modeling-schemas"></a>

Pelajari tentang paket desain skema pemodelan data untuk DynamoDB, termasuk kasus penggunaan, pola akses, dan desain skema akhir untuk jejaring sosial, profil game, manajemen keluhan, pembayaran berulang, status perangkat, dan toko online.

![\[Gambar menunjukkan hubungan konseptual antara data, blok yang berada di bawahnya, dan fondasi yang mendasari blok. Penekanan pada fondasi.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SchemaDesignData.png)


## Prasyarat
<a name="data-modeling-prereqs"></a>

Sebelum mencoba merancang skema untuk DynamoDB, kita harus terlebih dahulu mengumpulkan beberapa data prasyarat tentang kasus penggunaan yang perlu didukung oleh skema. Tidak seperti basis data relasional, DynamoDB dipecah secara default, artinya data akan berada di beberapa server di belakang layar sehingga desain lokalitas data menjadi hal yang penting. Kita harus menyusun daftar berikut untuk setiap desain skema:
+ Daftar entitas (Diagram ER)
+ Estimasi volume dan throughput untuk setiap entitas
+ Pola akses yang perlu didukung (kueri dan penulisan)
+ Persyaratan retensi data

**Topics**
+ [Prasyarat](#data-modeling-prereqs)
+ [Desain skema jejaring sosial di DynamoDB](data-modeling-schema-social-network.md)
+ [Desain skema profil game di DynamoDB](data-modeling-schema-gaming-profile.md)
+ [Desain skema sistem manajemen pengaduan di DynamoDB](data-modeling-complaint-management.md)
+ [Desain skema pembayaran berulang di DynamoDB](data-modeling-schema-recurring-payments.md)
+ [Memantau pembaruan status perangkat di DynamoDB](data-modeling-device-status.md)
+ [Menggunakan DynamoDB sebagai penyimpanan data untuk toko online](data-modeling-online-shop.md)

# Desain skema jejaring sosial di DynamoDB
<a name="data-modeling-schema-social-network"></a>

## Kasus penggunaan bisnis jejaring sosial
<a name="data-modeling-schema-social-network-use-case"></a>

Kasus penggunaan ini membahas penggunaan DynamoDB sebagai jejaring sosial. Jejaring sosial adalah layanan online yang memungkinkan berbagai pengguna berinteraksi satu sama lain. Jejaring sosial yang akan kita desain akan memungkinkan pengguna melihat garis waktu yang terdiri dari postingan mereka, pengikut mereka, orang yang mereka ikuti, dan postingan yang ditulis oleh orang yang mereka ikuti. Pola akses untuk desain skema ini adalah:
+ Mendapatkan informasi pengguna untuk userID tertentu 
+ Mendapatkan daftar pengikut untuk userID tertentu
+ Mendapatkan daftar orang yang diikuti untuk userID tertentu
+ Mendapatkan daftar postingan untuk userID tertentu
+ Mendapatkan daftar pengguna yang menyukai postingan untuk postID tertentu
+ Mendapatkan jumlah suka untuk postID tertentu
+ Mendapatkan lini masa untuk userID tertentu

## Diagram hubungan entitas jejaring sosial
<a name="data-modeling-schema-social-network-erd"></a>

Ini adalah diagram hubungan entitas (ERD) yang akan kita gunakan untuk desain skema jejaring sosial.

![\[ERD untuk aplikasi jejaring sosial yang menunjukkan entitas, seperti User, Post, dan Follower.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetworkERD.png)


## Pola akses jejaring sosial
<a name="data-modeling-schema-social-network-access-patterns"></a>

Ini adalah pola akses yang akan kita pertimbangkan untuk desain skema jaringan sosial.
+ `getUserInfoByUserID`
+ `getFollowerListByUserID`
+ `getFollowingListByUserID`
+ `getPostListByUserID`
+ `getUserLikesByPostID`
+ `getLikeCountByPostID`
+ `getTimelineByUserID`

## Evolusi desain skema jejaring sosial
<a name="data-modeling-schema-social-network-design-evolution"></a>

DynamoDB adalah basis data NoSQL, sehingga Anda tidak dapat melakukan penggabungan, yaitu operasi yang menggabungkan data dari beberapa basis data. Pelanggan yang tidak terbiasa dengan DynamoDB mungkin menerapkan filosofi desain sistem manajemen basis data relasional (RDBMS) (seperti membuat tabel untuk setiap entitas) ke DynamoDB ketika mereka tidak perlu melakukannya. Tujuan desain tabel tunggal DynamoDB adalah untuk menulis data dalam bentuk pra-penggabungan sesuai pola akses aplikasi, lalu segera menggunakan data tanpa komputasi tambahan. Untuk informasi selengkapnya, lihat [Single-table vs. multi-table design in DynamoDB](https://aws.amazon.com/blogs/database/single-table-vs-multi-table-design-in-amazon-dynamodb/). 

Sekarang, mari melanjutkan ke cara mengembangkan desain skema untuk menangani semua pola akses.

**Langkah 1: Tangani pola akses 1 (`getUserInfoByUserID`)**

Untuk mendapatkan informasi pengguna tertentu, kita perlu [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) tabel dasar dengan kondisi kunci `PK=<userID>`. Operasi kueri memungkinkan Anda melakukan paginasi hasil, yang berguna ketika pengguna memiliki banyak pengikut. Untuk informasi selengkapnya tentang Kueri, lihat [Menanyakan tabel di DynamoDB](Query.md). 

Dalam contoh, kita melacak dua jenis data untuk pengguna: yaitu "count" dan "info". "Count" pengguna mencerminkan berapa banyak pengikut yang dimiliki, berapa banyak pengguna yang diikuti, dan berapa banyak postingan yang telah dibuat. "Info" pengguna mencerminkan informasi pribadi seperti nama mereka.

Kita melihat dua jenis data yang diwakili oleh dua item di bawah ini. Item dengan "count" dalam kunci urutan (SK) lebih mungkin berubah daripada item dengan "info". DynamoDB menganggap ukuran item seperti yang muncul sebelum dan setelah pembaruan dan throughput yang disediakan akan mencerminkan ukuran item yang lebih besar. Meskipun Anda hanya memperbarui subset atribut item, [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) masih akan menggunakan throughput yang disediakan dalam jumlah penuh (lebih besar dari ukuran item sebelum dan sesudah). Anda bisa mendapatkan item melalui satu operasi `Query` dan menggunakan `UpdateItem` untuk menambah atau mengurangi dari atribut numerik yang ada.

![\[Hasil operasi Query untuk pengguna dengan ID u #12345 dan data hitungan dan info mereka.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork1.png)


**Langkah 2: Tangani pola akses 2 (`getFollowerListByUserID`)**

Untuk mendapatkan daftar pengguna yang mengikuti pengguna tertentu, kita perlu melakukan `Query` tabel dasar dengan kondisi kunci `PK=<userID>#follower`. 

![\[Hasil operasi Query pada tabel untuk daftar pengikut pengguna dengan ID u #12345.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork2.png)


**Langkah 3: Tangani pola akses 3 (`getFollowingListByUserID`)**

Untuk mendapatkan daftar pengguna yang diikuti pengguna tertentu, kita perlu melakukan `Query` tabel dasar dengan kondisi kunci `PK=<userID>#following`. Anda kemudian dapat menggunakan [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html)operasi untuk mengelompokkan beberapa permintaan bersama-sama dan melakukan hal berikut:
+ Tambahkan Pengguna A ke daftar pengikut Pengguna B, lalu tambahkan jumlah pengikut Pengguna B satu per satu.
+ Tambahkan Pengguna B ke daftar pengikut Pengguna A, lalu tambahkan jumlah pengikut Pengguna A satu per satu.

![\[Hasil operasi Query pada tabel untuk mencantumkan semua pengguna pengguna dengan ID u #12345 mengikuti.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork3.png)


**Langkah 4: Tangani pola akses 4 (`getPostListByUserID`)**

Untuk mendapatkan daftar postingan yang dibuat pengguna tertentu, kita perlu melakukan `Query` tabel dasar dengan kondisi kunci `PK=<userID>#post`. Satu hal penting yang perlu diperhatikan di sini adalah bahwa posting pengguna IDs harus inkremental: nilai PostID kedua harus lebih besar dari nilai PostID pertama (karena pengguna ingin melihat posting mereka dengan cara yang diurutkan). Anda dapat melakukan ini dengan membuat posting IDs berdasarkan nilai waktu seperti Universally Unique Lexicographically Sortable Identifier (ULID).

![\[Hasil operasi Query dengan kondisi kunci untuk mendapatkan daftar posting yang dibuat oleh pengguna tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork4.png)


**Langkah 5: Tangani pola akses 5 (`getUserLikesByPostID`)**

Untuk mendapatkan daftar pengguna yang menyukai postingan pengguna tertentu, kita perlu melakukan `Query` tabel dasar dengan kondisi kunci `PK=<postID>#likelist`. Pendekatan ini sama dengan pola yang kita gunakan untuk mengambil daftar pengikut dan pengguna yang diikuti dalam pola akses 2 (`getFollowerListByUserID`) dan pola akses 3 (`getFollowingListByUserID`).

![\[Hasil operasi Query dengan kondisi kunci untuk mendapatkan daftar pengguna yang menyukai posting pengguna tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork5.png)


**Langkah 6: Tangani pola akses 6 (`getLikeCountByPostID`)**

Untuk mendapatkan jumlah suka dalam posting tertentu, kita harus melakukan [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) operasi pada tabel dasar dengan kondisi kunci `PK=<postID>#likecount`. Pola akses ini dapat menyebabkan masalah throttling setiap kali pengguna dengan banyak pengikut (seperti selebritas) membuat postingan karena throttling terjadi ketika throughput partisi melebihi 1000 WCU per detik. Masalah ini tidak dihasilkan oleh DynamoDB, tetapi hanya muncul di DynamoDB karena berada di akhir tumpukan perangkat lunak.

Anda harus mengevaluasi apakah penting bahwa semua pengguna melihat jumlah suka secara bersamaan atau hal tersebut dapat dilakukan secara bertahap dari waktu ke waktu. Secara umum, jumlah suka postingan tidak harus langsung 100% akurat. Anda dapat menerapkan strategi ini dengan menempatkan antrean antara aplikasi Anda dan DynamoDB agar pembaruan terjadi secara berkala.

![\[Hasil GetItem operasi dengan kondisi kunci untuk mendapatkan hitungan suka untuk posting tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork6.png)


**Langkah 7: Tangani pola akses 7 (`getTimelineByUserID`)**

Untuk mendapatkan lini masa pengguna tertentu, kita harus melakukan `Query` operasi pada tabel dasar dengan kondisi kunci `PK=<userID>#timeline`. Mari pertimbangkan skenario ketika pengikut pengguna perlu melihat postingan secara sinkron. Setiap kali pengguna menulis postingan, daftar pengikut mereka dibaca dan userID serta postID mereka perlahan dimasukkan ke dalam kunci lini masa semua pengikutnya. Kemudian, ketika aplikasi Anda dimulai, Anda dapat membaca kunci lini masa dengan operasi `Query` dan mengisi layar lini masa dengan kombinasi userID dan postID menggunakan operasi [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html) untuk semua item baru. Anda tidak dapat membaca lini masa dengan panggilan API, tetapi ini adalah solusi yang lebih hemat biaya jika postingan sering diedit.

Lini masa adalah tempat yang menampilkan postingan terbaru, jadi kita perlu cara untuk membersihkan yang lama. Dibandingkan menggunakan WCU untuk menghapusnya, Anda dapat menggunakan fitur [TTL](TTL.md) DynamoDB untuk melakukannya secara gratis.

![\[Hasil operasi Query dengan kondisi kunci untuk mendapatkan timeline untuk pengguna tertentu yang menampilkan posting terbaru mereka.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork7.png)


Semua pola akses dan bagaimana desain skema mengatasinya dirangkum dalam tabel di bawah ini:


| Pola akses | Basis table/GSI/LSI | Operasi | Nilai kunci partisi | Nilai kunci urutan | Kondisi/filter lainnya | 
| --- | --- | --- | --- | --- | --- | 
| getUserInfoByUserID | Tabel dasar | Kueri | PK=<userID> |  |  | 
| getFollowerListByUserID | Tabel dasar | Kueri | PK=<userID>\$1follower |  |  | 
| getFollowingListByUserID | Tabel dasar | Kueri | PK=<userID>\$1following |  |  | 
| getPostListByUserID | Tabel dasar | Kueri | PK=<userID>\$1post |  |  | 
| getUserLikesByPostID | Tabel dasar | Kueri | PK=<postID>\$1likelist |  |  | 
| getLikeCountByPostID | Tabel dasar | GetItem | PK=<postID>\$1likecount |  |  | 
| getTimelineByuserID | Tabel dasar | Kueri | PK=<userID>\$1timeline |  |  | 

## Skema akhir jejaring sosial
<a name="data-modeling-schema-social-network-final-schema"></a>

Berikut adalah desain skema akhir. [Untuk mengunduh desain skema ini sebagai file JSON, lihat Contoh DynamoDB di.](https://github.com/aws-samples/aws-dynamodb-examples/blob/master/schema_design/SchemaExamples/SocialNetwork/SocialNetworkSchema.json) GitHub

**Tabel dasar:**

![\[Desain skema akhir dari tabel yang berisi hasil Query sebelumnya dan operasi. GetItem\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork8.png)


## Menggunakan NoSQL Workbench dengan desain skema ini
<a name="data-modeling-schema-social-network-nosql"></a>

Anda dapat mengimpor skema akhir ini ke [NoSQL Workbench](workbench.md), sebuah alat visual yang menyediakan fitur pemodelan data, visualisasi data, dan pengembangan kueri untuk DynamoDB, guna mengeksplorasi dan mengedit proyek baru Anda lebih lanjut. Ikuti langkah-langkah berikut untuk memulai:

1. Unduh NoSQL Workbench. Untuk informasi selengkapnya, lihat [Unduh NoSQL Workbench untuk DynamoDB](workbench.settingup.md).

1. Unduh file skema JSON yang tercantum di atas, yang sudah dalam format model NoSQL Workbench.

1. Impor file skema JSON ke NoSQL Workbench. Untuk informasi selengkapnya, lihat [Mengimpor model data yang ada](workbench.Modeler.ImportExisting.md). 

1. Setelah mengimpor model data ke NoSQL Workbench, Anda dapat mengeditnya. Lihat informasi yang lebih lengkap di [Mengedit model data yang ada](workbench.Modeler.Edit.md).

# Desain skema profil game di DynamoDB
<a name="data-modeling-schema-gaming-profile"></a>

## Kasus penggunaan bisnis profil game
<a name="data-modeling-schema-gaming-profile-use-case"></a>

Kasus penggunaan ini berbicara tentang penggunaan DynamoDB untuk menyimpan profil pemain untuk sistem game. Pengguna (dalam hal ini, pemain) perlu membuat profil sebelum mereka dapat berinteraksi dengan banyak game modern, terutama yang online. Profil game biasanya mencakup hal berikut:
+ Informasi dasar seperti nama pengguna
+ Data game seperti item dan peralatan
+ Catatan game seperti tugas dan aktivitas
+ Informasi sosial seperti daftar teman

Untuk memenuhi persyaratan akses kueri data ketat untuk aplikasi ini, kunci primer (kunci partisi dan kunci urutan) akan menggunakan nama generik (PK dan SK) agar dapat dibebani dengan berbagai jenis nilai seperti yang akan kita lihat di bawah ini.

Pola akses untuk desain skema ini adalah:
+ Mendapatkan daftar teman pengguna
+ Mendapatkan semua informasi pemain
+ Mendapatkan daftar item pengguna
+ Mendapatkan item tertentu dari daftar item pengguna
+ Memperbarui karakter pengguna
+ Memperbarui jumlah item untuk pengguna

Ukuran profil game akan bervariasi di game yang berbeda. [Mengompresi nilai atribut yang besar](bp-use-s3-too.md) dapat membuatnya sesuai dengan batas item di DynamoDB dan mengurangi biaya. Strategi manajemen throughput akan bergantung pada berbagai faktor, seperti: jumlah pemain, jumlah game yang dimainkan per detik, dan beban kerja musiman. Biasanya untuk game yang baru diluncurkan, jumlah pemain dan tingkat popularitasnya tidak diketahui, jadi kita akan mulai dengan mode [throughput sesuai permintaan](capacity-mode.md#capacity-mode-on-demand).

## Diagram hubungan entitas profil game
<a name="data-modeling-schema-gaming-profile-erd"></a>

Ini adalah diagram hubungan entitas (ERD) yang akan kita gunakan untuk desain skema sistem profil game.

![\[Diagram ER untuk profil game, menunjukkan hubungan antar entitas, seperti Pengguna, Game, dan Skor.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/GamingProfileERD.png)


## Pola akses profil game
<a name="data-modeling-schema-gaming-profile-access-patterns"></a>

Ini adalah pola akses yang akan kita pertimbangkan untuk desain skema jaringan sosial.
+ `getPlayerFriends`
+ `getPlayerAllProfile`
+ `getPlayerAllItems`
+ `getPlayerSpecificItem`
+ `updateCharacterAttributes`
+ `updateItemCount`

## Evolusi desain skema profil game
<a name="data-modeling-schema-social-network-design-evolution"></a>

Dari ERD di atas, kita dapat melihat bahwa ini adalah tipe one-to-many hubungan pemodelan data. Dalam DynamoDB one-to-many, model data dapat diatur ke dalam koleksi item, yang berbeda dari database relasional tradisional di mana beberapa tabel dibuat dan ditautkan melalui kunci asing. [Koleksi item](WorkingWithItemCollections.md) adalah sekelompok item yang berbagi nilai kunci partisi yang sama, tetapi memiliki nilai kunci urutan yang berbeda. Dalam koleksi item, setiap item memiliki nilai kunci urutan unik yang membedakannya dari item lainnya. Dengan pertimbangan ini, mari kita gunakan pola berikut untuk nilai `HASH` dan `RANGE` untuk setiap jenis entitas.

Untuk memulai, kita menggunakan nama generik seperti `PK` dan `SK` untuk menyimpan berbagai jenis entitas dalam tabel yang sama agar model bisa tetap digunakan hingga ke depannya. Untuk keterbacaan yang lebih baik, kita dapat menyertakan prefiks untuk menunjukkan jenis data atau menyertakan atribut arbitrer yang disebut `Entity_type` atau `Type`. Dalam contoh saat ini, kita menggunakan string yang dimulai dengan `player` untuk menyimpan `player_ID` sebagai `PK`; gunakan `entity name#` sebagai prefiks `SK`, dan tambahkan atribut `Type` untuk menunjukkan jenis entitas bagian data ini. Hal ini memungkinkan kami untuk mendukung penyimpanan lebih banyak jenis entitas ke depannya, dan menggunakan teknologi canggih seperti GSI Overloading dan Sparse GSI untuk memenuhi lebih banyak pola akses.

Mari kita mulai menerapkan pola akses. Pola akses seperti menambahkan pemain dan menambahkan peralatan dapat diwujudkan melalui operasi [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html), jadi kita dapat mengabaikannya. Dalam dokumen ini, kita akan fokus pada pola akses tipikal yang tercantum di atas.

**Langkah 1: Atasi pola akses 1 (`getPlayerFriends`)**

Kita mengatasi pola akses 1 (`getPlayerFriends`) dengan langkah ini. Dalam desain kita saat ini, pertemanan bersifat sederhana dan jumlah teman dalam game ini kecil. Agar simpel, kita menggunakan jenis data daftar untuk menyimpan daftar teman (pemodelan 1:1). Dalam desain ini, kita menggunakan [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) untuk memenuhi pola akses ini. Dalam operasi `GetItem`, kita secara eksplisit memberikan kunci partisi dan nilai kunci urutan untuk mendapatkan item tertentu.

Namun, jika sebuah game memiliki banyak teman, dan hubungan di antara mereka rumit (seperti pertemanan menjadi dua arah dengan komponen undangan dan penerimaan), perlu menggunakan many-to-many hubungan untuk menyimpan setiap teman secara individual, untuk skala ke ukuran daftar teman yang tidak terbatas. Dan jika perubahan pertemanan melibatkan operasi pada beberapa item pada saat yang sama, transaksi DynamoDB dapat digunakan untuk mengelompokkan beberapa tindakan bersama-sama dan mengirimkannya sebagai satu atau all-or-nothing [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html)operasi. [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)

![\[Diagram many-to-many hubungan kompleks untuk profil game entitas Teman.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/GamingProfile1.png)


**Langkah 2: Tangani pola akses 2 (`getPlayerAllProfile`), 3 (`getPlayerAllItems`), dan 4 (`getPlayerSpecificItem`) **

Kita menangani pola akses 2 (`getPlayerAllProfile`), 3 (`getPlayerAllItems`), dan 4 (`getPlayerSpecificItem`) menggunakan langkah ini. Kesamaan ketiga pola akses ini adalah kueri rentang, yang menggunakan operasi [`Query`](Query.md). Bergantung pada ruang lingkup kueri, [Kondisi Kunci](Query.KeyConditionExpressions.md) dan [Ekspresi Filter](Query.FilterExpression.md) digunakan, yang umum digunakan dalam pengembangan praktis.

Dalam operasi Kueri, kita memberikan nilai tunggal untuk Kunci Partisi dan mendapatkan semua item dengan nilai Kunci Partisi tersebut. Pola akses 2 (`getPlayerAllProfile`) diimplementasikan dengan cara ini. Secara opsional, kita dapat menambahkan ekspresi kondisi kunci urutan — sebuah string yang menentukan item yang akan dibaca dari tabel. Pola akses 3 (`getPlayerAllItems`) diimplementasikan dengan menambahkan kondisi kunci dari kunci urutan begins\$1with `ITEMS#`. Selanjutnya, untuk menyederhanakan pengembangan sisi aplikasi, kita dapat menggunakan ekspresi filter untuk mengimplementasikan pola akses 4 (`getPlayerSpecificItem`).

Berikut adalah contoh kode pseudo menggunakan ekspresi filter yang memfilter item dari kategori `Weapon`:

```
filterExpression: "ItemType = :itemType"
expressionAttributeValues: {":itemType": "Weapon"}
```

![\[Menggunakan operasi Query dengan kunci partisi dan mengurutkan kondisi kunci untuk menerapkan pola akses yang berbeda.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/GamingProfile2.png)


**catatan**  
Filter ekspresi diterapkan setelah Kueri selesai, namun sebelum hasilnya dikembalikan ke klien. Oleh karena itu, Kueri menggunakan jumlah kapasitas baca yang sama, terlepas dari ada atau tidak adanya ekspresi filter.

Jika pola aksesnya adalah melakukan kueri pada set data besar dan menyaring sejumlah besar data untuk menyimpan sebagian kecil data saja, pendekatan yang tepat adalah merancang Kunci Partisi dan Kunci Urutan DynamoDB secara lebih efektif. Misalnya, dalam contoh di atas untuk mendapatkan `ItemType` tertentu, jika ada banyak item untuk setiap pemain dan melakukan kueri untuk `ItemType` tertentu adalah pola akses yang tipikal, membawa `ItemType` ke `SK` sebagai kunci komposit merupakan hal yang lebih efisien. Model data akan terlihat seperti ini: `ITEMS#ItemType#ItemId`.

**Langkah 3: Atasi pola akses 5 (`updateCharacterAttributes`) dan 6 (`updateItemCount`)**

Kita menangani pola akses 5 (`updateCharacterAttributes`), dan 6 (`updateItemCount`) menggunakan langkah ini. Ketika pemain perlu memodifikasi karakter, seperti mengurangi mata uang, atau memodifikasi jumlah senjata tertentu dalam item mereka, gunakan [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) untuk menerapkan pola akses ini. Untuk memperbarui mata uang pemain tetapi juga memastikannya tidak pernah berada di bawah jumlah minimum, kita dapat menambahkan [Contoh CLI ekspresi kondisi DynamoDB](Expressions.ConditionExpressions.md) untuk mengurangi saldo hanya jika saldo lebih besar dari atau sama dengan jumlah minimum. Berikut adalah contoh kode pseudo:

```
UpdateExpression: "SET currency = currency - :amount"
ConditionExpression: "currency >= :minAmount"
```

![\[Menggunakan UpdateItem dengan ekspresi kondisi untuk memodifikasi mata uang pemain, memastikan itu tidak pernah kurang dari jumlah yang ditetapkan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/GamingProfile4-Update-player-Currency.png)


Saat melakukan pengembangan dengan DynamoDB dan menggunakan [Penghitung Atom](WorkingWithItems.md#WorkingWithItems.AtomicCounters) untuk mengurangi inventaris, kita dapat memastikan idempotensi menggunakan penguncian optimis. Berikut adalah contoh kode pseudo untuk Penghitung Atom:

```
UpdateExpression: "SET ItemCount = ItemCount - :incr"
expression-attribute-values: '{":incr":{"N":"1"}}'
```

![\[Menggunakan penghitung atom untuk mengurangi nilai ItemCount atribut dari 5 menjadi 4.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/GamingProfile5-Update-Item-Count.png)


Selain itu, dalam skenario di mana pemain membeli item dengan mata uang, seluruh proses perlu mengurangi mata uang dan menambahkan item pada saat yang sama. Kita dapat menggunakan Transaksi DynamoDB untuk mengelompokkan beberapa tindakan bersama-sama dan mengirimkannya sebagai satu atau all-or-nothing `TransactWriteItems` operasi. `TransactGetItems` `TransactWriteItems`adalah operasi penulisan sinkron dan idempoten yang mengelompokkan hingga 100 tindakan penulisan dalam satu operasi. all-or-nothing Tindakan tersebut diselesaikan secara atomik, sehingga semuanya berhasil atau tidak satu pun yang berhasil. Transaksi membantu menghilangkan risiko duplikasi atau hilangnya mata uang. Untuk informasi selengkapnya tentang transaksi, lihat [Contoh DynamoDB transactions](transaction-example.md).

Semua pola akses dan bagaimana desain skema mengatasinya dirangkum dalam tabel di bawah ini:


| Pola akses | Basis table/GSI/LSI | Operasi | Nilai kunci partisi | Nilai kunci urutan | Kondisi/filter lainnya | 
| --- | --- | --- | --- | --- | --- | 
| getPlayerFriends | Tabel dasar | GetItem | PK=PlayerID | SK=“FRIENDS\$1playerID” |  | 
| getPlayerAllProfil | Tabel dasar | Kueri | PK=PlayerID |  |  | 
| getPlayerAllBarang | Tabel dasar | Kueri | PK=PlayerID | SK begins\$1with “ITEMS\$1” |  | 
| getPlayerSpecificBarang | Tabel dasar | Kueri | PK=PlayerID | SK begins\$1with “ITEMS\$1” | filterExpression: "ItemType =:itemType”: \$1“:itemType” expressionAttributeValues: “Senjata”\$1 | 
| updateCharacterAttributes | Tabel dasar | UpdateItem | PK=PlayerID | SK=“\$1METADATA\$1playerID” | UpdateExpression: “SET mata uang = mata uang -:jumlah”: “mata ConditionExpression uang>=:minAmount” | 
| updateItemCount | Tabel dasar | UpdateItem | PK=PlayerID | SK =“ITEMS\$1ItemID” | update-expression: “SET ItemCount = ItemCount -:incr”: '\$1” :incr” expression-attribute-values: \$1"N” :"1"\$1\$1'  | 

## Skema akhir profil game
<a name="data-modeling-schema-gaming-profile-final-schema"></a>

Berikut adalah desain skema akhir. [Untuk mengunduh desain skema ini sebagai file JSON, lihat Contoh DynamoDB di.](https://github.com/aws-samples/aws-dynamodb-examples/blob/master/schema_design/SchemaExamples/GamingPlayerProfiles/GamePlayerProfilesSchema.json) GitHub

**Tabel dasar:**

![\[Desain skema akhir dari tabel yang berisi hasil implementasi pola akses sebelumnya.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/GamingProfile6-FinalSchema.png)


## Menggunakan NoSQL Workbench dengan desain skema ini
<a name="data-modeling-schema-gaming-profile-nosql"></a>

Anda dapat mengimpor skema akhir ini ke [NoSQL Workbench](workbench.md), sebuah alat visual yang menyediakan fitur pemodelan data, visualisasi data, dan pengembangan kueri untuk DynamoDB, guna mengeksplorasi dan mengedit proyek baru Anda lebih lanjut. Ikuti langkah-langkah berikut untuk memulai:

1. Unduh NoSQL Workbench. Untuk informasi selengkapnya, lihat [Unduh NoSQL Workbench untuk DynamoDB](workbench.settingup.md).

1. Unduh file skema JSON yang tercantum di atas, yang sudah dalam format model NoSQL Workbench.

1. Impor file skema JSON ke NoSQL Workbench. Untuk informasi selengkapnya, lihat [Mengimpor model data yang ada](workbench.Modeler.ImportExisting.md). 

1. Setelah mengimpor model data ke NoSQL Workbench, Anda dapat mengeditnya. Lihat informasi yang lebih lengkap di [Mengedit model data yang ada](workbench.Modeler.Edit.md).

# Desain skema sistem manajemen pengaduan di DynamoDB
<a name="data-modeling-complaint-management"></a>

## Kasus penggunaan bisnis sistem manajemen pengaduan
<a name="data-modeling-schema-complaint-management-use-case"></a>

DynamoDB adalah basis data yang cocok untuk kasus penggunaan sistem manajemen pengaduan (atau pusat kontak) karena sebagian besar pola akses yang terkait dengannya adalah pencarian transaksional berbasis kunci-nilai. Pola akses tipikal dalam skenario ini adalah:
+ Membuat dan memperbarui pengaduan
+ Mengeskalasi pengaduan
+ Membuat dan membaca komentar tentang pengaduan
+ Mendapatkan semua pengaduan dari pelanggan
+ Mendapatkan semua komentar oleh agen dan mendapatkan semua eskalasi 

Beberapa komentar mungkin memiliki lampiran yang menjelaskan pengaduan atau solusi. Meskipun ini semua adalah pola akses kunci-nilai, mungkin ada persyaratan tambahan seperti mengirimkan pemberitahuan ketika komentar baru ditambahkan ke pengaduan atau menjalankan kueri analitik untuk menemukan distribusi pengaduan berdasarkan tingkat keparahan (atau kinerja agen) per minggu. Persyaratan tambahan yang terkait dengan manajemen siklus hidup atau kepatuhan adalah mengarsipkan data pengaduan yang sudah tercatat selama tiga tahun.

## Diagram arsitektur sistem manajemen pengaduan
<a name="data-modeling-schema-complaint-management-ad"></a>

Diagram berikut menunjukkan diagram arsitektur sistem manajemen keluhan. Diagram ini menunjukkan Layanan AWS integrasi berbeda yang digunakan sistem manajemen keluhan.

![\[Alur kerja gabungan untuk memenuhi persyaratan non-transaksional menggunakan integrasi dengan beberapa. Layanan AWS\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-1-AD.jpg)


Terlepas dari pola akses transaksional kunci-nilai yang akan kita tangani di bagian pemodelan data DynamoDB nanti, ada tiga persyaratan non-transaksional. Diagram arsitektur di atas dapat dipecah menjadi tiga alur kerja berikut:

1. Kirim pemberitahuan saat komentar baru ditambahkan ke pengaduan

1. Jalankan kueri analitik pada data mingguan

1. Arsipkan data yang berusia lebih dari tiga tahun

Mari kita lihat setiap alur kerja tersebut lebih mendalam.

**Kirim pemberitahuan saat komentar baru ditambahkan ke pengaduan**

Kita dapat menggunakan alur kerja di bawah ini untuk mencapai persyaratan ini:

![\[Alur kerja untuk memanggil fungsi Lambda untuk mengirim pemberitahuan berdasarkan perubahan yang direkam oleh DynamoDB Streams.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-2-Workflow1.jpg)


[DynamoDB Streams](Streams.md) adalah mekanisme pengambilan data perubahan untuk merekam semua aktivitas tulis pada tabel DynamoDB Anda. Anda dapat mengonfigurasi fungsi Lambda untuk memicu beberapa atau semua perubahan ini. [Filter peristiwa](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) dapat dikonfigurasi pada pemicu Lambda untuk memfilter peristiwa yang tidak relevan dengan kasus penggunaan. Dalam instans ini, kita dapat menggunakan filter untuk memicu Lambda hanya ketika komentar baru ditambahkan dan mengirimkan pemberitahuan ke ID email yang relevan yang dapat diambil dari [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) atau penyimpanan kredensial lainnya.

**Jalankan kueri analitik pada data mingguan**

DynamoDB cocok untuk beban kerja yang utamanya difokuskan pada pemrosesan transaksional online (OLTP). Untuk 10-20% pola akses lainnya dengan persyaratan analitik, data dapat diekspor ke S3 dengan fitur [Ekspor ke Amazon S3](S3DataExport.HowItWorks.md) yang dikelola tanpa berdampak pada lalu lintas langsung di tabel DynamoDB. Lihat alur kerja di bawah ini:

![\[Alur kerja untuk menjalankan fungsi Lambda secara berkala untuk menyimpan data DynamoDB di bucket Amazon S3.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-3-Workflow2.jpg)


[Amazon EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is) dapat digunakan untuk memicu AWS Lambda sesuai jadwal - ini memungkinkan Anda mengonfigurasi ekspresi cron agar pemanggilan Lambda berlangsung secara berkala. Lambda dapat menginvokasi panggilan API `ExportToS3` dan menyimpan data DynamoDB di S3. Data S3 ini kemudian dapat diakses oleh mesin SQL seperti [Amazon Athena](https://docs.aws.amazon.com/athena/latest/ug/what-is) untuk menjalankan kueri analitik pada data DynamoDB tanpa memengaruhi beban kerja transaksional langsung pada tabel. Contoh kueri Athena untuk menemukan jumlah pengaduan per tingkat keparahan akan terlihat seperti ini:

```
SELECT Item.severity.S as "Severity", COUNT(Item) as "Count"
FROM "complaint_management"."data"
WHERE NOT Item.severity.S = ''
GROUP BY Item.severity.S ;
```

Hal ini memunculkan hasil kueri Athena berikut:

![\[Hasil kueri Athena menunjukkan jumlah keluhan untuk tingkat keparahan P3, P2, dan P1.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-4-Athena.png)


**Arsipkan data yang berusia lebih dari tiga tahun**

Anda dapat memanfaatkan fitur [Waktu untuk Beroperasi (TTL](TTL.md)) DynamoDB guna menghapus data usang dari tabel DynamoDB Anda tanpa biaya tambahan (kecuali dalam kasus replika tabel global untuk versi 2019.11.21 (Terbaru), di mana penghapusan TTL yang direplikasi ke Wilayah lain akan mengonsumsi kapasitas tulis). Data ini muncul dan dapat dikonsumsi dari DynamoDB Streams untuk diarsipkan ke Amazon S3. Alur kerja untuk persyaratan ini adalah sebagai berikut:

![\[Alur kerja untuk mengarsipkan data lama di bucket Amazon S3 menggunakan fitur TTL dan DynamoDB Streams.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-5-Workflow3.jpg)


## Diagram hubungan entitas sistem manajemen pengaduan
<a name="data-modeling-schema-complaint-management-erd"></a>

Ini adalah diagram hubungan entitas (ERD) yang akan kita gunakan untuk desain skema sistem manajemen pengaduan. 

![\[Sistem manajemen keluhan ERD yang menunjukkan entitas Pelanggan, Keluhan, Komentar, dan Agen.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-6-ERD.jpg)


## Pola akses sistem manajemen pengaduan
<a name="data-modeling-schema-complaint-management-access-patterns"></a>

Ini adalah pola akses yang akan kita pertimbangkan untuk desain skema manajemen pengaduan.

1. createComplaint

1. updateComplaint

1. updateSeveritybyComplaintID

1. getComplaintByKeluhanD

1. addCommentByKeluhanD

1. getAllCommentsByComplaintID

1. getLatestCommentByComplaintID

1. dapatkan IDAnd keluhan AComplaintby pelangganID

1. getAllComplaintsByCustomerID

1. escalateComplaintByKeluhanD

1. getAllEscalatedKeluhan

1. getEscalatedComplaintsByAgentID (pesanan dari yang terbaru ke terlama)

1. getCommentsByAgenTid (antara dua tanggal)

## Evolusi desain skema sistem manajemen pengaduan
<a name="data-modeling-schema-complaint-management-design-evolution"></a>

Karena ini adalah sistem manajemen pengaduan, sebagian besar pola akses berkisar pada pengaduan sebagai entitas utama. `ComplaintID` yang sangat penting akan memastikan distribusi data yang merata di partisi-partisi yang mendasarinya, dan juga merupakan kriteria pencarian yang paling umum untuk pola akses yang teridentifikasi. Oleh karena itu, `ComplaintID` adalah kandidat kunci partisi yang baik dalam set data ini.

**Langkah 1: Tangani pola akses 1 (`createComplaint`), 2 (`updateComplaint`), 3 (`updateSeveritybyComplaintID`), dan 4 (`getComplaintByComplaintID`) **

Kita dapat menggunakan kunci urutan umum yang disebut "metadata" (atau "AA") untuk menyimpan informasi khusus pengaduan seperti`CustomerID`, `State`, `Severity`, dan `CreationDate`. Kita menggunakan operasi tunggal dengan `PK=ComplaintID` dan `SK=“metadata”` untuk melakukan hal berikut:

1. [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) untuk membuat pengaduan baru

1. [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) untuk memperbarui tingkat keparahan atau bidang lain dalam metadata pengaduan

1. [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) untuk mengambil metadata untuk pengaduan

![\[Kunci primer, kunci sortir, dan nilai atribut, seperti customer_id dan tingkat keparahan, untuk item keluhan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-7-Step1.png)


**Langkah 2: Atasi pola akses 5 (`addCommentByComplaintID`)**

Pola akses ini membutuhkan model one-to-many hubungan antara keluhan dan komentar atas keluhan. Kita akan menggunakan teknik [partisi vertikal](data-modeling-blocks.md#data-modeling-blocks-vertical-partitioning) di sini untuk menggunakan kunci urutan dan membuat koleksi item dengan berbagai jenis data. Jika kita melihat pola akses 6 (`getAllCommentsByComplaintID`) dan 7 (`getLatestCommentByComplaintID`), kita tahu bahwa komentar perlu diurutkan berdasarkan waktu. Beberapa komentar dapat masuk pada saat yang sama, sehingga kita dapat menggunakan teknik [kunci urutan komposit](data-modeling-blocks.md#data-modeling-blocks-composite) untuk menambahkan waktu dan `CommentID` di atribut kunci urutan.

Opsi lain untuk menangani kemungkinan benturan komentar seperti itu adalah dengan meningkatkan perincian stempel waktu atau menambahkan angka tambahan sebagai sufiks alih-alih menggunakan `Comment_ID`. Dalam hal ini, kita akan mengawali nilai kunci urutan untuk item yang sesuai dengan komentar dengan “comm\$1” untuk mengaktifkan operasi berbasis kisaran.

Kita juga perlu memastikan bahwa `currentState` dalam metadata pengaduan mencerminkan keadaan saat komentar baru ditambahkan. Menambahkan komentar mungkin menunjukkan bahwa pengaduan telah ditugaskan ke agen atau telah diselesaikan dan lain sebagainya. Untuk menggabungkan penambahan komentar dan pembaruan status saat ini dalam metadata keluhan, all-or-nothing dengan cara tertentu, kami akan menggunakan API. [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) Status tabel kini terlihat seperti ini:

![\[Tabel untuk menyimpan keluhan dengan komentarnya sebagai one-to-many hubungan menggunakan kunci sortir komposit.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-8-Step2.png)


Kita tambahkan beberapa data lagi dalam tabel dan juga tambahkan `ComplaintID` sebagai bidang terpisah dari `PK` kita untuk pemeriksaan model di masa depan jika kita membutuhkan indeks tambahan di `ComplaintID`. Perhatikan juga bahwa beberapa komentar mungkin memiliki lampiran yang akan kami simpan di Amazon Simple Storage Service dan hanya mempertahankan referensi mereka atau URLs di DynamoDB. Hal ini adalah praktik terbaik untuk menjaga basis data transaksional seramping mungkin untuk mengoptimalkan biaya dan performa. Data sekarang terlihat seperti ini:

![\[Tabel dengan metadata keluhan dan data semua komentar yang terkait dengan setiap keluhan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-9-Step3.png)


**Langkah 3: Atasi pola akses 6 (`getAllCommentsByComplaintID`) dan 7 (`getLatestCommentByComplaintID`)**

Untuk mendapatkan semua komentar untuk pengaduan, kita dapat menggunakan operasi [`query`](Query.md) dengan kondisi `begins_with` pada kunci urutan. Daripada menghabiskan kapasitas baca tambahan untuk membaca entri metadata dan kemudian menyaring hasil yang relevan, memiliki kondisi kunci urutan seperti ini membantu kita untuk hanya membaca apa yang kita butuhkan. Misalnya, operasi kueri dengan `PK=Complaint123` dan `SK` begins\$1with `comm#` akan mengembalikan yang berikut saat melewatkan entri metadata:

![\[Hasil operasi kueri menggunakan kondisi kunci pengurutan yang hanya displyas komentar keluhan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-10-Step4.png)


Karena kita memerlukan komentar terbaru untuk pengaduan dalam pola 7 (`getLatestCommentByComplaintID`), mari kita gunakan dua parameter kueri tambahan:

1. `ScanIndexForward` harus diatur ke False untuk mendapatkan hasil yang diurutkan dalam urutan menurun

1. `Limit` harus diatur ke 1 untuk mendapatkan (hanya satu) komentar terbaru

Mirip dengan pola akses 6 (`getAllCommentsByComplaintID`), kita melewatkan entri metadata menggunakan `begins_with` `comm#` sebagai kondisi kunci urutan. Sekarang, Anda dapat melakukan pola akses 7 pada desain ini menggunakan operasi kueri dengan `PK=Complaint123` dan `SK=begins_with comm#`, `ScanIndexForward=False`, serta `Limit` 1. Item yang ditargetkan berikut akan dikembalikan sebagai hasilnya:

![\[Hasil operasi kueri menggunakan kondisi kunci pengurutan untuk mendapatkan komentar terakhir keluhan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-11-Step5.png)


Mari tambahkan lebih banyak data dummy ke tabel.

![\[Tabel dengan data dummy untuk mendapatkan komentar terbaru tentang keluhan yang diterima.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-12-Step6.png)


**Langkah 4: Atasi pola akses 8 (`getAComplaintbyCustomerIDAndComplaintID`) dan 9 (`getAllComplaintsByCustomerID`)**

Pola akses 8 (`getAComplaintbyCustomerIDAndComplaintID`) dan 9 (`getAllComplaintsByCustomerID`) memperkenalkan kriteria pencarian baru:`CustomerID`. Mengambilnya dari tabel yang ada memerlukan [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) yang mahal untuk membaca semua data dan kemudian memfilter item yang relevan untuk `CustomerID` yang bersangkutan. Kita dapat membuat pencarian ini lebih efisien dengan membuat [indeks sekunder global (GSI)](GSI.md) dengan `CustomerID` sebagai kunci partisi. Mengingat one-to-many hubungan antara pelanggan dan keluhan serta pola akses 9 (`getAllComplaintsByCustomerID`), `ComplaintID` akan menjadi kandidat yang tepat untuk kunci pengurutan.

Data di GSI akan terlihat seperti ini:

![\[GSI dengan model one-to-many hubungan untuk mendapatkan semua keluhan oleh CustomerID tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-13-Step4-GSI.png)


 Contoh kueri pada GSI ini untuk pola akses 8 (`getAComplaintbyCustomerIDAndComplaintID`) adalah: `customer_id=custXYZ`, `sort key=Complaint1321`. Hasilnya akan menjadi:

![\[Hasil operasi kueri pada GSI untuk mendapatkan data keluhan tertentu oleh pelanggan tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-14-Step4-8.png)


Untuk mendapatkan semua pengaduan bagi pelanggan untuk pola akses 9 (`getAllComplaintsByCustomerID`), kueri pada GSI adalah: `customer_id=custXYZ` sebagai kondisi kunci partisi. Hasilnya akan menjadi:

![\[Hasil operasi kueri menggunakan kondisi kunci partisi untuk mendapatkan semua keluhan oleh pelanggan tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-15-Step4-9.png)


**Langkah 5: Atasi pola akses 10 (`escalateComplaintByComplaintID`)**

Akses ini memperkenalkan aspek eskalasi. Untuk mengeskalasi pengaduan, kita dapat menggunakan `UpdateItem` untuk menambahkan atribut seperti `escalated_to` dan `escalation_time` ke item metadata pengaduan yang ada. DynamoDB menyediakan desain skema fleksibel yang berarti satu set atribut non-kunci dapat dibuat seragam atau terpisah di berbagai item. Lihat contohnya di bawah ini:

`UpdateItem with PK=Complaint1444, SK=metadata`

![\[Hasil pemutakhiran metadata keluhan menggunakan operasi UpdateItem API.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-16-Step5.png)


**Langkah 6: Atasi pola akses 11 (`getAllEscalatedComplaints`) dan 12 (`getEscalatedComplaintsByAgentID`)**

Hanya segelintir pengaduan yang diharapkan akan dieskalasikan dari seluruh set data. Oleh karena itu, membuat indeks pada atribut terkait eskalasi akan menghasilkan pencarian yang efisien serta penyimpanan GSI yang hemat biaya. Kita bisa melakukan hal ini dengan memanfaatkan teknik [indeks jarang](data-modeling-blocks.md#data-modeling-blocks-sparse-index). GSI dengan kunci partisi sebagai `escalated_to` dan kunci urutan sebagai `escalation_time` akan terlihat seperti ini:

![\[Desain GSI menggunakan atribut terkait eskalasi, escalated_to dan escalation_time.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-17-Step6.png)


Untuk mendapatkan semua pengaduan yang dieskalasikan untuk pola akses 11 (`getAllEscalatedComplaints`), kita cukup memindai GSI ini. Perhatikan bahwa pemindaian ini akan berperforma baik dan hemat biaya karena ukuran GSI. Untuk mendapatkan pengaduan yang dieskalasikan untuk agen tertentu (pola akses 12 (`getEscalatedComplaintsByAgentID`)), kunci partisi akan berupa `escalated_to=agentID` dan kita mengatur `ScanIndexForward` ke `False` untuk mengurutkan dari yang terbaru ke yang terlama.

**Langkah 7: Atasi pola akses 13 (`getCommentsByAgentID`)**

Untuk pola akses terakhir, kita perlu melakukan pencarian berdasarkan dimensi baru: `AgentID`. Kita juga membutuhkan pengurutan berbasis waktu untuk membaca komentar di antara dua tanggal, jadi kita membuat GSI dengan `agent_id` sebagai kunci partisi dan `comm_date` sebagai kunci urutan. Data dalam GSI ini akan terlihat seperti berikut:

![\[Desain GSI untuk mencari komentar oleh agen tertentu yang diurutkan menggunakan tanggal komentar.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-18.png)


Contoh kueri pada GSI ini adalah `partition key agentID=AgentA` dan `sort key=comm_date between (2023-04-30T12:30:00, 2023-05-01T09:00:00)`, yang hasilnya adalah:

![\[Hasil kueri menggunakan kunci partisi dan kunci sortir pada GSI.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-19.png)


Semua pola akses dan bagaimana desain skema mengatasinya dirangkum dalam tabel di bawah ini:


| Pola akses | Basis table/GSI/LSI | Operasi | Nilai kunci partisi | Nilai kunci urutan | Kondisi/filter lainnya | 
| --- | --- | --- | --- | --- | --- | 
| createComplaint | Tabel dasar | PutItem | PK=complaint\$1id | SK=metadata |  | 
| updateComplaint | Tabel dasar | UpdateItem | PK=complaint\$1id | SK=metadata |  | 
| updateSeveritybyComplaintID | Tabel dasar | UpdateItem | PK=complaint\$1id | SK=metadata |  | 
| getComplaintByKeluhanD | Tabel dasar | GetItem | PK=complaint\$1id | SK=metadata |  | 
| addCommentByKeluhanD | Tabel dasar | TransactWriteItems | PK=complaint\$1id | SK=metadata, SK=comm\$1comm\$1date\$1comm\$1id |  | 
| getAllCommentsByComplaintID | Tabel dasar | Kueri | PK=complaint\$1id | SK begins\$1with "comm\$1" |  | 
| getLatestCommentByComplaintID | Tabel dasar | Kueri | PK=complaint\$1id | SK begins\$1with "comm\$1" | scan\$1index\$1forward=False, Limit 1 | 
| dapatkan IDAnd keluhan AComplaintby pelangganID | Customer\$1complaint\$1GSI | Kueri | customer\$1id=customer\$1id | complaint\$1id = complaint\$1id |  | 
| getAllComplaintsByCustomerID | Customer\$1complaint\$1GSI | Kueri | customer\$1id=customer\$1id | N/A |  | 
| escalateComplaintByKeluhanD | Tabel dasar | UpdateItem | PK=complaint\$1id | SK=metadata |  | 
| getAllEscalatedKeluhan | Escalations\$1GSI | Scan | N/A | N/A |  | 
| getEscalatedComplaintsByAgentID (pesanan dari yang terbaru ke terlama) | Escalations\$1GSI | Kueri | escalated\$1to=agent\$1id | N/A | scan\$1index\$1forward=False | 
| getCommentsByAgenTid (antara dua tanggal) | Agents\$1Comments\$1GSI | Kueri | agent\$1id=agent\$1id | SK antara (date1, date2) |  | 

## Skema akhir sistem manajemen pengaduan
<a name="data-modeling-schema-complaint-management-final-schema"></a>

Berikut adalah desain skema akhir. [Untuk mengunduh desain skema ini sebagai file JSON, lihat Contoh DynamoDB di.](https://github.com/aws-samples/aws-dynamodb-examples/blob/master/schema_design/SchemaExamples/ComplainManagement/ComplaintManagementSchema.json) GitHub

**Tabel dasar**

![\[Desain meja dasar dengan metadata keluhan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-20-Complaint_management_system.png)


**Customer\$1Complaint\$1GSI**

![\[Desain GSI menunjukkan keluhan oleh pelanggan tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-21-Customer_Complaint_GSI.png)


**Escalations\$1GSI**

![\[Desain GSI menunjukkan atribut terkait eskalasi.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-22-Escalations_GSI.png)


**Agents\$1Comments\$1GSI**

![\[Desain GSI menunjukkan komentar yang dibuat oleh agen tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ComplaintManagement-23-Comments_GSI.png)


## Menggunakan NoSQL Workbench dengan desain skema ini
<a name="data-modeling-schema-complaint-management-nosql"></a>

Anda dapat mengimpor skema akhir ini ke [NoSQL Workbench](workbench.md), sebuah alat visual yang menyediakan fitur pemodelan data, visualisasi data, dan pengembangan kueri untuk DynamoDB, guna mengeksplorasi dan mengedit proyek baru Anda lebih lanjut. Ikuti langkah-langkah berikut untuk memulai:

1. Unduh NoSQL Workbench. Untuk informasi selengkapnya, lihat [Unduh NoSQL Workbench untuk DynamoDB](workbench.settingup.md).

1. Unduh file skema JSON yang tercantum di atas, yang sudah dalam format model NoSQL Workbench.

1. Impor file skema JSON ke NoSQL Workbench. Untuk informasi selengkapnya, lihat [Mengimpor model data yang ada](workbench.Modeler.ImportExisting.md). 

1. Setelah mengimpor model data ke NoSQL Workbench, Anda dapat mengeditnya. Lihat informasi yang lebih lengkap di [Mengedit model data yang ada](workbench.Modeler.Edit.md).

# Desain skema pembayaran berulang di DynamoDB
<a name="data-modeling-schema-recurring-payments"></a>

## Kasus penggunaan bisnis pembayaran berulang
<a name="data-modeling-schema-recurring-payments-use-case"></a>

Kasus penggunaan ini membahas penggunaan DynamoDB untuk menerapkan sistem pembayaran berulang. Model data memiliki entitas berikut: *akun*, *langganan*, dan *tanda terima*. Spesifikasi untuk kasus penggunaan kita meliputi hal berikut:
+ Setiap *akun* dapat memiliki beberapa *langganan*
+ *Langganan* memiliki `NextPaymentDate` ketika pembayaran berikutnya perlu diproses dan `NextReminderDate` ketika pengingat email dikirim ke pelanggan
+ Ada item untuk *langganan* yang disimpan dan diperbarui saat pembayaran diproses (ukuran item rata-rata sekitar 1 KB dan throughput-nya tergantung jumlah *akun* dan *langganan*)
+ Pemroses *pembayaran* juga akan membuat *tanda terima* sebagai bagian dari proses yang disimpan dalam tabel dan diatur agar kedaluwarsa setelah jangka waktu tertentu dengan menggunakan atribut [TTL](TTL.md)

## Diagram hubungan entitas pembayaran berulang
<a name="data-modeling-schema-recurring-payments-erd"></a>

Ini adalah diagram hubungan entitas (ERD) yang akan kita gunakan untuk desain skema sistem pembayaran berulang.

![\[ERD sistem pembayaran berulang yang menunjukkan entitas: Akun, Langganan, dan Tanda Terima.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-1-ERD.png)


## Pola akses sistem pembayaran berulang
<a name="data-modeling-schema-recurring-payments-access-patterns"></a>

Ini adalah pola akses yang akan kita pertimbangkan untuk desain skema pembayaran berulang.

1. `createSubscription`

1. `createReceipt`

1. `updateSubscription`

1. `getDueRemindersByDate`

1. `getDuePaymentsByDate`

1. `getSubscriptionsByAccount`

1. `getReceiptsByAccount`

## Desain skema pembayaran berulang
<a name="data-modeling-schema-recurring-payments-design-evolution"></a>

Nama generik `PK` dan `SK` digunakan untuk atribut kunci guna memungkinkan penyimpanan berbagai jenis entitas dalam tabel yang sama seperti entitas akun, langganan, dan tanda terima. Pertama, pengguna membuat langganan dan setuju untuk membayar sejumlah biaya pada hari yang sama setiap bulan sebagai harga atas suatu produk. Pengguna dapat memilih salah satu hari dalam sebulan untuk memproses pembayaran. Terdapat juga pengingat yang akan dikirim sebelum pembayaran diproses. Aplikasi bekerja dengan menjalankan dua tugas batch yang berjalan setiap hari: satu tugas batch mengirimkan pengingat yang jatuh tempo hari itu dan tugas batch lainnya memproses semua pembayaran yang jatuh tempo hari itu.

**Langkah 1: Tangani pola akses 1 (`createSubscription`)**

Pola akses 1 (`createSubscription`) awalnya digunakan untuk membuat langganan, dan detail yang mencakup `SKU`, `NextPaymentDate`, `NextReminderDate`, dan `PaymentDetails` diatur. Langkah ini menunjukkan status tabel hanya untuk satu akun dengan satu langganan. Mungkin ada beberapa langganan dalam koleksi item jadi ini adalah one-to-many hubungan.

![\[Desain tabel yang menunjukkan detail langganan untuk akun.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-2-Step1.png)


**Langkah 2: Tangani pola akses 2 (`createReceipt`) dan 3 (`updateSubscription`)**

Pola akses 2 (`createReceipt`) digunakan untuk membuat item tanda terima. Setelah pembayaran diproses setiap bulan, pemroses pembayaran akan menulis tanda terima kembali ke tabel dasar. Di sana, bisa ada beberapa tanda terima dalam koleksi item jadi ini adalah one-to-many hubungan. Pemroses pembayaran juga akan memperbarui item langganan (Pola akses 3 (`updateSubscription`)) untuk memperbarui `NextReminderDate` atau `NextPaymentDate` bulan berikutnya.

![\[Detail tanda terima dan pembaruan item langganan untuk menampilkan tanggal pengingat langganan berikutnya.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-3-Step2.png)


**Langkah 3: Tangani pola akses 4 (`getDueRemindersByDate`)**

Aplikasi memproses pengingat untuk pembayaran dalam batch untuk hari ini. Oleh karena itu, aplikasi perlu mengakses langganan pada dimensi yang berbeda, yaitu tanggal, bukan akun. Kasus penggunaan ini bagus untuk [indeks sekunder global (GSI)](GSI.md). Pada langkah ini kita menambahkan indeks `GSI-1`, yang menggunakan `NextReminderDate` sebagai kunci partisi GSI. Kita tidak perlu mereplikasi semua item. GSI ini adalah [indeks jarang](data-modeling-blocks.md#data-modeling-blocks-sparse-index) dan item tanda terima tidak direplikasi. Kita juga tidak perlu memproyeksikan semua atribut—kita hanya perlu menyertakan subset atribut. Gambar di bawah ini menunjukkan skema `GSI-1` dan memberikan informasi yang diperlukan aplikasi untuk mengirim email pengingat.

![\[Skema GSI-1 dengan detail, seperti alamat email, aplikasi perlu mengirim email pengingat.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-4-Step3.png)


**Langkah 4: Tangani pola akses 5 (`getDuePaymentsByDate`)**

Aplikasi memproses pembayaran dalam batch untuk hari ini dengan cara yang sama seperti pengingat. Kita menambahkan indeks `GSI-2` pada langkah ini, yang menggunakan `NextPaymentDate` sebagai kunci partisi GSI. Kita tidak perlu mereplikasi semua item. GSI ini adalah indeks jarang dan item tanda terima tidak direplikasi. Gambar di bawah ini menunjukkan skema `GSI-2`.

![\[Skema GSI-2 dengan detail untuk memproses pembayaran. NextPaymentDate adalah kunci partisi untuk GSI-2.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-5-Step4.png)


**Langkah 5: Tangani pola akses 6 (`getSubscriptionsByAccount`) dan 7 (`getReceiptsByAccount`)**

Aplikasi dapat mengambil semua langganan untuk akun dengan menggunakan [kueri](Query.md) pada tabel dasar yang menargetkan pengidentifikasi akun (`PK`) dan menggunakan operator rentang untuk mendapatkan semua item dengan “SUB\$1” sebagai awalan `SK`. Aplikasi juga dapat menggunakan struktur kueri yang sama untuk mengambil semua tanda terima menggunakan operator rentang untuk mendapatkan semua item dengan “REC\$1” sebagai awalan `SK`. Hal ini memungkinkan kita memenuhi pola akses 6 (`getSubscriptionsByAccount`) dan 7 (`getReceiptsByAccount`). Aplikasi menggunakan pola akses tersebut sehingga pengguna dapat melihat langganan saat ini dan tanda terima lama mereka selama enam bulan terakhir. Tidak ada perubahan pada skema tabel dalam langkah ini dan kita dapat melihat di bawah ini bagaimana kita hanya menargetkan item berlangganan dalam pola akses 6 (`getSubscriptionsByAccount`).

![\[Hasil operasi query pada tabel dasar. Ini menunjukkan berlangganan akun tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-6-Step5.png)


Semua pola akses dan bagaimana desain skema mengatasinya dirangkum dalam tabel di bawah ini:


| Pola akses | Basis table/GSI/LSI | Operasi | Nilai kunci partisi | Nilai kunci urutan | 
| --- | --- | --- | --- | --- | 
| createSubscription | Tabel dasar | PutItem | ACC\$1account\$1id | SUB\$1<SUBID>\$1SKU<SKUID> | 
| createReceipt | Tabel dasar | PutItem | ACC\$1account\$1id | REC\$1< > \$1SKU RecieptDate <SKUID> | 
| updateSubscription | Tabel dasar | UpdateItem | ACC\$1account\$1id | SUB\$1<SUBID>\$1SKU<SKUID> | 
| getDueRemindersByDate | GSI-1 | Kueri | <NextReminderDate> |  | 
| getDuePaymentsByDate | GSI-2 | Kueri | <NextPaymentDate> |  | 
| getSubscriptionsByAkun | Tabel dasar | Kueri | ACC\$1account\$1id | SK begins\$1with “SUB\$1” | 
| getReceiptsByAkun | Tabel dasar | Kueri | ACC\$1account\$1id | SK begins\$1with “REC\$1” | 

## Skema akhir pembayaran berulang
<a name="data-modeling-schema-recurring-payments-final-schema"></a>

Berikut adalah desain skema akhir. [Untuk mengunduh desain skema ini sebagai file JSON, lihat Contoh DynamoDB di.](https://github.com/aws-samples/aws-dynamodb-examples/blob/master/schema_design/SchemaExamples/ReocurringPayments/ReocurringPaymentsSchema.json) GitHub

**Tabel dasar**

![\[Desain tabel dasar yang menampilkan informasi akun, serta detail langganan dan tanda terima.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-7-Base.png)


**GSI-1**

![\[Skema GSI-1 dengan rincian berlangganan, seperti alamat email dan. NextPaymentDate\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-8-GSI1.png)


**GSI-2**

![\[Skema GSI-2 dengan rincian pembayaran, seperti dan. PaymentAmount PaymentDay\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/ReoccurringPayments-9-GSI2.png)


## Menggunakan NoSQL Workbench dengan desain skema ini
<a name="data-modeling-schema-recurring-payments-nosql"></a>

Anda dapat mengimpor skema akhir ini ke [NoSQL Workbench](workbench.md), sebuah alat visual yang menyediakan fitur pemodelan data, visualisasi data, dan pengembangan kueri untuk DynamoDB, guna mengeksplorasi dan mengedit proyek baru Anda lebih lanjut. Ikuti langkah-langkah berikut untuk memulai:

1. Unduh NoSQL Workbench. Untuk informasi selengkapnya, lihat [Unduh NoSQL Workbench untuk DynamoDB](workbench.settingup.md).

1. Unduh file skema JSON yang tercantum di atas, yang sudah dalam format model NoSQL Workbench.

1. Impor file skema JSON ke NoSQL Workbench. Untuk informasi selengkapnya, lihat [Mengimpor model data yang ada](workbench.Modeler.ImportExisting.md). 

1. Setelah mengimpor model data ke NoSQL Workbench, Anda dapat mengeditnya. Lihat informasi yang lebih lengkap di [Mengedit model data yang ada](workbench.Modeler.Edit.md).

# Memantau pembaruan status perangkat di DynamoDB
<a name="data-modeling-device-status"></a>

Kasus penggunaan ini membahas tentang penggunaan DynamoDB untuk memantau pembaruan status perangkat (atau perubahan status perangkat) di DynamoDB.

## Kasus penggunaan
<a name="data-modeling-schema-device-status-use-case"></a>

Dalam kasus penggunaan IoT (pabrik pintar misalnya), banyak perangkat yang perlu dipantau oleh operator dan perangkat tersebut secara berkala mengirim status atau log ke sistem pemantauan. Ketika ada masalah dengan sebuah perangkat, status perangkat tersebut berubah dari *normal* menjadi *peringatan*. Ada tingkat log atau status yang berbeda tergantung tingkat keparahan dan jenis perilaku abnormal pada perangkat. Sistem kemudian menugaskan operator untuk memeriksa perangkat dan mereka dapat mengeskalasikan masalah kepada supervisor jika diperlukan.

Beberapa pola akses tipikal untuk sistem ini meliputi:
+ Membuat entri log untuk sebuah perangkat
+ Mendapatkan semua log untuk status perangkat tertentu yang menampilkan log terbaru terlebih dahulu
+ Mendapatkan semua log untuk operator tertentu di antara dua tanggal
+ Mendapatkan semua log yang dieskalasi untuk supervisor tertentu
+ Mendapatkan semua log yang dieskalasi dengan status perangkat tertentu untuk supervisor tertentu
+ Mendapatkan semua log yang dieskalasi dengan status perangkat tertentu untuk supervisor tertentu pada tanggal tertentu

## Diagram hubungan entitas
<a name="data-modeling-schema-device-status-erd"></a>

Ini adalah diagram hubungan entitas (ERD) yang akan kita gunakan untuk memantau pembaruan status perangkat.

![\[ERD pembaruan status perangkat. Ini menunjukkan entitas: Perangkat dan Operator.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-1-ERD.jpg)


## Pola akses
<a name="data-modeling-schema-device-status-access-patterns"></a>

Ini adalah pola akses yang akan kita pertimbangkan untuk memantau pembaruan status perangkat.

1. `createLogEntryForSpecificDevice`

1. `getLogsForSpecificDevice`

1. `getWarningLogsForSpecificDevice`

1. `getLogsForOperatorBetweenTwoDates`

1. `getEscalatedLogsForSupervisor`

1. `getEscalatedLogsWithSpecificStatusForSupervisor`

1. `getEscalatedLogsWithSpecificStatusForSupervisorForDate`

## Evolusi desain skema
<a name="data-modeling-schema-device-status-design-evolution"></a>

**Langkah 1: Atasi pola akses 1 (`createLogEntryForSpecificDevice`) dan 2 (`getLogsForSpecificDevice`)**

Unit penskalaan untuk sistem pelacakan perangkat adalah perangkat individual. Dalam sistem ini, `deviceID` mengidentifikasi perangkat secara unik. Ini menjadikan `deviceID` kandidat yang baik untuk kunci partisi. Setiap perangkat mengirim informasi ke sistem pelacakan secara berkala (misalnya, setiap lima menit atau lebih). Pengurutan ini menjadikan tanggal sebagai kriteria pengurutan logis dan oleh karena itu, menjadi kunci urutan. Data sampel dalam kasus ini akan terlihat seperti ini:

![\[Tabel untuk menyimpan status beberapa perangkat. DeviceID adalah kunci utama dan pembaruan status Tanggal adalah kunci pengurutan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-2-Step1.png)


Untuk mengambil entri log perangkat tertentu, kita dapat melakukan operasi [kueri](Query.md) dengan kunci partisi `DeviceID="d#12345"`.

**Langkah 2: Atasi pola akses 3 (`getWarningLogsForSpecificDevice`)**

Karena `State` merupakan atribut non-kunci, mengatasi pola akses 3 dengan skema saat ini akan memerlukan [ekspresi filter](Query.FilterExpression.md). Di DynamoDB, ekspresi filter diterapkan setelah data dibaca menggunakan ekspresi kondisi kunci. Misalnya, jika kita mengambil log peringatan untuk`d#12345`, operasi kueri dengan kunci partisi `DeviceID="d#12345"` akan membaca empat item dari tabel di atas dan kemudian menyaring satu item tanpa status *peringatan*. Pendekatan ini tidak efisien dalam skala besar. Ekspresi filter dapat menjadi cara yang baik untuk mengecualikan item dalam kueri jika rasio item yang dikecualikan rendah atau kueri jarang dilakukan. Namun, untuk kasus dengan banyak item diambil dari tabel dan sebagian besar item disaring, kita dapat terus mengembangkan desain tabel agar berjalan lebih efisien.

Mari kita ubah cara menangani pola akses ini menggunakan [kunci urutan komposit](data-modeling-blocks.md#data-modeling-blocks-composite). Anda dapat mengimpor data sampel dari [DeviceStateLog\$13.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_3.json) di mana kunci pengurutan diubah menjadi. `State#Date` Kunci urutan ini adalah komposisi atribut `State`, `#`, dan `Date`. Dalam contoh ini, `#` digunakan sebagai pembatas. Data sekarang terlihat seperti ini: 

![\[Data pembaruan status untuk perangkat, d #12345, diambil menggunakan kunci sortir komposit Status #Date.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-3-Step2.png)


Untuk mengambil log peringatan untuk perangkat saja, kueri menjadi lebih tertarget dengan skema ini. Kondisi kunci untuk kueri menggunakan kunci partisi `DeviceID="d#12345"` dan kunci urutan `State#Date begins_with “WARNING”`. Kueri ini hanya akan membaca tiga item yang relevan dengan status *peringatan*.

**Langkah 3: Atasi pola akses 4 (`getLogsForOperatorBetweenTwoDates`)**

Anda dapat mengimpor [DeviceStateLog\$14.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_4.json) D di mana `Operator` atribut ditambahkan ke `DeviceStateLog` tabel dengan contoh data.

![\[DeviceStateLog desain tabel dengan atribut Operator untuk mendapatkan log operator antara tanggal tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-4-Step3.png)


Karena `Operator` bukan kunci partisi, tidak ada cara untuk melakukan pencarian nilai kunci langsung pada tabel ini berdasarkan `OperatorID`. Kita perlu membuat [koleksi item](WorkingWithItemCollections.md) baru dengan indeks sekunder global aktif pada `OperatorID`. Pola akses memerlukan pencarian berdasarkan tanggal, sehingga Tanggal adalah atribut kunci urutan untuk [indeks sekunder global (GSI)](GSI.md). Tampilan GSI sekarang menjadi:

![\[Desain GSI dengan OperatorId dan Date sebagai kunci partisi dan kunci sortir untuk mendapatkan log untuk operator tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-5-Step3.png)


Untuk pola akses 4 (`getLogsForOperatorBetweenTwoDates`), Anda dapat mengueri GSI ini dengan kunci partisi `OperatorID=Liz` dan kunci urutan `Date` antara `2020-04-11T05:58:00` dan `2020-04-24T14:50:00`.

![\[Query pada GSI menggunakan OperatorId dan Date untuk mendapatkan log untuk operator antara dua tanggal.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-6-GSI1_1.png)


**Langkah 4: Tangani pola akses 5 (`getEscalatedLogsForSupervisor`), 6 (`getEscalatedLogsWithSpecificStatusForSupervisor`), dan 7 (`getEscalatedLogsWithSpecificStatusForSupervisorForDate`)**

Kami akan menggunakan [indeks jarang](data-modeling-blocks.md#data-modeling-blocks-sparse-index) untuk mengatasi pola akses ini.

Indeks sekunder global secara default bersifat jarang, jadi hanya item dalam tabel dasar yang berisi atribut kunci primer indeks yang benar-benar akan muncul di indeks. Ini adalah cara lain untuk mengecualikan item yang tidak relevan untuk pola akses yang dimodelkan.

Anda dapat mengimpor [DeviceStateLog\$16.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_6.json) di mana `EscalatedTo` atribut ditambahkan ke `DeviceStateLog` tabel dengan contoh data. Seperti disebutkan sebelumnya, tidak semua log akan dieskalasikan ke supervisor.

![\[Desain GSI dengan EscalatedTo atribut untuk mendapatkan semua log yang ditingkatkan untuk supervisor.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-7-Step4.png)


Anda sekarang dapat membuat GSI baru di mana `EscalatedTo` adalah kunci partisi dan `State#Date` adalah kunci urutan. Perhatikan bahwa hanya item yang memiliki atribut `EscalatedTo` dan `State#Date` yang muncul dalam indeks.

![\[Desain GSI untuk mendapatkan semua item dengan atribut EscalatedTo dan State #Date.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-8-Step4.png)


Pola akses lainnya dirangkum sebagai berikut:

    Untuk pola akses 5 (getEscalatedLogsForSupervisor), Anda dapat melakukan kueri pada eskalasi GSI dengan kunci partisi EscalatedTo ="Sara”   Untuk pola akses 6 (getEscalatedLogsWithSpecificStatusForSupervisor), Anda dapat melakukan kueri pada eskalasi GSI dengan kunci partisi EscalatedTo ="Sara” dan mengurutkan kunci Status \$1Date begins\$1with “WARNING”    Untuk pola akses 7 (getEscalatedLogsWithSpecificStatusForSupervisorForDate), Anda dapat melakukan kueri pada eskalasi GSI dengan kunci partisi EscalatedTo ="Sara” dan mengurutkan kunci Status \$1Date begins\$1with “\$12020 -04-27” WARNING4    

Semua pola akses dan bagaimana desain skema mengatasinya dirangkum dalam tabel di bawah ini:


| Pola akses | Basis table/GSI/LSI | Operasi | Nilai kunci partisi | Nilai kunci urutan | Kondisi/filter lainnya | 
| --- | --- | --- | --- | --- | --- | 
| createLogEntryForSpecificDevice | Tabel dasar | PutItem | DeviceID=deviceId | State\$1Date=state\$1date |  | 
| getLogsForSpecificDevice | Tabel dasar | Kueri | DeviceID=deviceId | State\$1Date begins\$1with "state1\$1" | ScanIndexForward = Salah | 
| getWarningLogsForSpecificDevice | Tabel dasar | Kueri | DeviceID=deviceId | State\$1Date begins\$1with "WARNING" |  | 
| getLogsForOperatorBetweenTwoDates | GSI-1 | Kueri | Operator=operatorName | Tanggal antara date1 dan date2 |  | 
| getEscalatedLogsForSupervisor | GSI-2 | Kueri | EscalatedTo=Nama pengawas |  |  | 
| getEscalatedLogsWithSpecificStatusForSupervisor | GSI-2 | Kueri | EscalatedTo=Nama pengawas | State\$1Date begins\$1with "state1\$1" |  | 
| getEscalatedLogsWithSpecificStatusForSupervisorForDate | GSI-2 | Kueri | EscalatedTo=Nama pengawas | State\$1Date begins\$1with "state1\$1date1" |  | 

## Skema akhir
<a name="data-modeling-schema-device-status-final-schema"></a>

Berikut adalah desain skema akhir. [Untuk mengunduh desain skema ini sebagai file JSON, lihat Contoh DynamoDB di.](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/schema_design/SchemaExamples) GitHub

**Tabel dasar**

![\[Desain tabel dasar dengan metadata status perangkat, seperti ID Perangkat, Status, dan Tanggal.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-9-Table.png)


**GSI-1**

![\[Desain GSI-1. Ini menunjukkan kunci utama dan atribut: deviceId, State #Date, dan State.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-10-GSI1.png)


**GSI-2**

![\[Desain GSI-2. Ini menunjukkan kunci utama dan atribut: DeviceId, Operator, Date, dan State.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-11-GSI2.png)


## Menggunakan NoSQL Workbench dengan desain skema ini
<a name="data-modeling-schema-device-status-nosql"></a>

Anda dapat mengimpor skema akhir ini ke [NoSQL Workbench](workbench.md), sebuah alat visual yang menyediakan fitur pemodelan data, visualisasi data, dan pengembangan kueri untuk DynamoDB, guna mengeksplorasi dan mengedit proyek baru Anda lebih lanjut. Ikuti langkah-langkah berikut untuk memulai:

1. Unduh NoSQL Workbench. Untuk informasi selengkapnya, lihat [Unduh NoSQL Workbench untuk DynamoDB](workbench.settingup.md).

1. Unduh file skema JSON yang tercantum di atas, yang sudah dalam format model NoSQL Workbench.

1. Impor file skema JSON ke NoSQL Workbench. Untuk informasi selengkapnya, lihat [Mengimpor model data yang ada](workbench.Modeler.ImportExisting.md). 

1. Setelah mengimpor model data ke NoSQL Workbench, Anda dapat mengeditnya. Lihat informasi yang lebih lengkap di [Mengedit model data yang ada](workbench.Modeler.Edit.md).

# Menggunakan DynamoDB sebagai penyimpanan data untuk toko online
<a name="data-modeling-online-shop"></a>

Kasus penggunaan ini membahas penggunaan DynamoDB sebagai penyimpanan data untuk toko online (atau e-store).

## Kasus penggunaan
<a name="data-modeling-schema-online-shop"></a>

Toko online memungkinkan pengguna menelusuri berbagai produk dan pada akhirnya membelinya. Berdasarkan faktur yang dihasilkan, pelanggan dapat membayar menggunakan kode diskon atau kartu hadiah lalu membayar jumlah yang tersisa dengan kartu kredit. Produk yang dibeli akan diambil dari salah satu gudang dan akan dikirim ke alamat yang diberikan. Pola akses umum untuk toko online meliputi:
+ Mendapatkan pelanggan untuk customerId tertentu
+ Mendapatkan produk untuk productId tertentu
+ Mendapatkan gudang untuk warehouseId tertentu
+ Mendapatkan inventaris produk untuk semua gudang berdasarkan productId
+ Mendapatkan pesanan untuk orderId tertentu
+ Mendapatkan semua produk untuk orderId tertentu
+ Mendapatkan faktur untuk orderId tertentu
+ Mendapatkan semua pengiriman untuk orderId tertentu
+ Mendapatkan semua pesanan untuk productId tertentu dan rentang tanggal tertentu
+ Mendapatkan faktur untuk invoiceId tertentu
+ Mendapatkan semua pembayaran untuk invoiceId tertentu
+ Mendapatkan detail pengiriman untuk shipmentId tertentu
+ Mendapatkan semua pengiriman untuk warehouseId tertentu
+ Mendapatkan inventaris semua produk untuk warehouseId tertentu
+ Mendapatkan semua faktur untuk customerId tertentu dan rentang tanggal tertentu
+ Mendapatkan semua produk yang dipesan untuk customerId tertentu dan rentang tanggal tertentu

## Diagram hubungan entitas
<a name="data-modeling-schema-online-shop-erd"></a>

Ini adalah diagram hubungan entitas (ERD) yang akan kita gunakan untuk memodelkan DynamoDB sebagai penyimpanan data untuk toko online.

![\[ERD untuk model data toko online dengan entitas, seperti Produk, Pesanan, Pembayaran, dan Pelanggan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-1-ERD.png)


## Pola akses
<a name="data-modeling-schema-online-shop-access-patterns"></a>

Ini adalah pola akses yang akan dipertimbangkan saat menggunakan DynamoDB sebagai penyimpanan data untuk toko online.

1. `getCustomerByCustomerId`

1. `getProductByProductId`

1. `getWarehouseByWarehouseId`

1. `getProductInventoryByProductId`

1. `getOrderDetailsByOrderId`

1. `getProductByOrderId`

1. `getInvoiceByOrderId`

1. `getShipmentByOrderId`

1. `getOrderByProductIdForDateRange`

1. `getInvoiceByInvoiceId`

1. `getPaymentByInvoiceId`

1. `getShipmentDetailsByShipmentId`

1. `getShipmentByWarehouseId`

1. `getProductInventoryByWarehouseId`

1. `getInvoiceByCustomerIdForDateRange`

1. `getProductsByCustomerIdForDateRange`

## Evolusi desain skema
<a name="data-modeling-schema-online-shop-design-evolution"></a>

Menggunakan[NoSQL Workbench untuk DynamoDB](workbench.md), import [AnOnlineShop\$11.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_1.json) untuk membuat model data baru dipanggil `AnOnlineShop` dan tabel baru dipanggil. `OnlineShop` Perhatikan bahwa kita menggunakan nama generik `PK` dan `SK` untuk kunci partisi dan kunci urutan. Hal ini adalah praktik yang digunakan untuk menyimpan berbagai jenis entitas dalam tabel yang sama.

**Langkah 1: Tangani pola akses 1 (`getCustomerByCustomerId`)**

Impor [AnOnlineShop\$12.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_2.json) untuk menangani pola akses 1 (). `getCustomerByCustomerId` Beberapa entitas tidak memiliki hubungan dengan entitas lain, jadi kita akan menggunakan nilai yang sama dari `PK` dan `SK` untuk entitas tersebut. Dalam contoh data, perhatikan bahwa kunci menggunakan prefiks `c#` untuk membedakan `customerId` dari entitas lain yang akan ditambahkan nanti. Praktik ini diulang untuk entitas lain juga. 

Untuk menangani pola akses ini, operasi [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) dapat digunakan dengan `PK=customerId` dan `SK=customerId`.

**Langkah 2: Tangani pola akses 2 (`getProductByProductId`)**

Impor [AnOnlineShop\$13.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_3.json) ke alamat pola akses 2 (`getProductByProductId`) untuk entitas. `product` Entitas produk diawali oleh `p#` dan atribut kunci urutan yang sama digunakan untuk menyimpan `customerID` serta `productID`. Penamaan generik dan [partisi vertikal](data-modeling-blocks.md#data-modeling-blocks-vertical-partitioning) memungkinkan kita membuat koleksi item untuk desain tabel tunggal yang efektif. 

Untuk menangani pola akses ini, operasi `GetItem` dapat digunakan dengan `PK=productId` dan `SK=productId`.

**Langkah 3: Tangani pola akses 3 (`getWarehouseByWarehouseId`)**

Impor [AnOnlineShop\$14.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_4.json) ke alamat pola akses 3 (`getWarehouseByWarehouseId`) untuk entitas. `warehouse` Saat ini entitas `customer`, `product`, dan `warehouse` ditambahkan ke tabel yang sama. Entitas tersebut dibedakan menggunakan prefiks dan atribut `EntityType`. Atribut jenis (atau penamaan prefiks) meningkatkan keterbacaan model. Keterbacaan akan terpengaruh jika kita hanya menyimpan alfanumerik IDs untuk entitas yang berbeda dalam atribut yang sama. Akan sulit untuk membedakan satu entitas dari yang lain tanpa adanya pengidentifikasi ini. 

Untuk menangani pola akses ini, operasi `GetItem` dapat digunakan dengan `PK=warehouseId` dan `SK=warehouseId`.

**Tabel dasar:**

![\[Desain tabel DynamoDB dengan awalan EntityType dan untuk mendapatkan data gudang dengan ID-nya.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-2-Step3.png)


**Langkah 4: Tangani pola akses 4 (`getProductInventoryByProductId`)**

Impor [AnOnlineShop\$15.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_5.json) ke pola akses alamat 4 (). `getProductInventoryByProductId` `warehouseItem`entitas digunakan untuk melacak jumlah produk di setiap gudang. Item ini biasanya akan diperbarui ketika produk ditambahkan atau dihapus dari gudang. Seperti yang terlihat di ERD, ada many-to-many hubungan antara `product` dan`warehouse`. Di sini, one-to-many hubungan dari `product` ke `warehouse` dimodelkan sebagai`warehouseItem`. Nantinya, one-to-many hubungan dari `warehouse` hingga `product` akan dimodelkan juga. 

Pola akses 4 dapat ditangani dengan kueri pada `PK=ProductId` dan `SK begins_with “w#“`. 

Untuk informasi selengkapnya tentang `begins_with()` dan ekspresi lain yang dapat diterapkan ke kunci urutan, lihat [Ekspresi Kondisi Kunci](Query.KeyConditionExpressions.md).

**Tabel dasar:**

![\[Desain tabel untuk menanyakan ProductID dan WarehouseID untuk melacak inventaris produk di gudang tertentu.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-3-Step4.png)


**Langkah 5: Tangani pola akses 5 (`getOrderDetailsByOrderId`) dan 6 (`getProductByOrderId`)**

Tambahkan beberapa lagi`customer`,`product`, dan `warehouse` item ke tabel dengan mengimpor [AnOnlineShop\$16.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_6.json). Kemudian, impor [AnOnlineShop\$17.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_7.json) untuk membuat koleksi item `order` yang dapat mengatasi pola akses 5 (`getOrderDetailsByOrderId`) dan 6 (). `getProductByOrderId` Anda dapat melihat one-to-many hubungan antara `order` dan `product` dimodelkan sebagai entitas OrderItem. 

Untuk menangani pola akses 5 (`getOrderDetailsByOrderId`), lakukan kueri tabel dengan `PK=orderId`. Tindakan ini akan memberikan semua informasi tentang pesanan termasuk `customerId` dan produk yang dipesan.

**Tabel dasar:**

![\[Desain tabel untuk kueri menggunakan orderId untuk mendapatkan informasi tentang semua produk yang dipesan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-4-Step5.png)


Untuk menagani pola akses 6 (`getProductByOrderId`), kita hanya perlu membaca produk dalam `order`. Kueri tabel dengan `PK=orderId` dan `SK begins_with “p#”` untuk mencapai hal ini.

**Tabel dasar:**

![\[Desain tabel untuk kueri menggunakan OrderId dan productID untuk mendapatkan produk dalam urutan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-5-Step5.png)


**Langkah 6: Tangani pola akses 7 (`getInvoiceByOrderId`)**

Impor [AnOnlineShop\$18.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_8.json) untuk menambahkan `invoice` entitas ke koleksi item *pesanan* untuk menangani pola akses 7 (). `getInvoiceByOrderId` Untuk menangani pola akses ini, operasi `PK=orderId` dan `SK begins_with “i#”` dapat digunakan.

**Tabel dasar:**

![\[Desain tabel dengan entitas faktur dalam koleksi item pesanan untuk mendapatkan faktur oleh OrderId.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-6-Step6.png)


**Langkah 7: Tangani pola akses 8 (`getShipmentByOrderId`)**

Impor [AnOnlineShop\$19.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_9.json) untuk menambahkan `shipment` entitas ke koleksi item *pesanan* untuk mengatasi pola akses 8 (). `getShipmentByOrderId` Model yang dipartisi secara vertikal yang sama diperluas dengan menambahkan lebih banyak jenis entitas dalam desain tabel tunggal. Perhatikan bagaimana koleksi item *pesanan* berisi hubungan yang berbeda dari hubungan entitas `order` dengan entitas`shipment`, `orderItem`, dan `invoice`. 

Untuk mendapatkan pengiriman berdasarkan `orderId`, Anda dapat melakukan operasi kueri dengan `PK=orderId` dan `SK begins_with “sh#”`.

**Tabel dasar:**

![\[Desain tabel dengan entitas pengiriman ditambahkan ke koleksi barang pesanan untuk mendapatkan pengiriman dengan ID pesanan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-7-Step7.png)


**Langkah 8: Tangani pola akses 9 (`getOrderByProductIdForDateRange`)**

Kita membuat koleksi item *pesanan* pada langkah sebelumnya. Pola akses ini memiliki dimensi pencarian baru (`ProductID` dan `Date`) yang mengharuskan Anda memindai seluruh tabel dan memfilter catatan yang relevan untuk mengambil item yang ditargetkan. Untuk menangani pola akses ini, kita harus membuat [indeks sekunder global (GSI)](GSI.md). *Impor [AnOnlineShop\$110.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_10.json) untuk membuat koleksi item baru menggunakan GSI yang memungkinkan untuk mengambil `orderItem` data dari beberapa koleksi item pesanan.* Sekarang data memiliki `GSI1-PK` dan `GSI1-SK` yang masing-masing akan menjadi kunci partisi dan kunci urutan `GSI1`. 

DynamoDB otomatis mengisi item yang berisi atribut kunci GSI dari tabel ke GSI. Tidak perlu melakukan penyisipan tambahan secara manual ke GSI. 

Untuk menangani pola akses 9, lakukan kueri `GSI1` dengan `GSI1-PK=productId` dan `GSI1SK between (date1, date2)`.

**Tabel dasar:**

![\[Desain tabel dengan GSI untuk mendapatkan data pesanan dari beberapa koleksi item pesanan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-8-Step8-Base.png)


**GSI1:**

![\[Desain GSI dengan ProductID dan Date sebagai partisi dan kunci pengurutan untuk mendapatkan pesanan berdasarkan ID dan tanggal produk.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-9-Step8-GSI.png)


**Langkah 9: Tangani pola akses 10 (`getInvoiceByInvoiceId`) dan 11 (`getPaymentByInvoiceId`)**

Impor [AnOnlineShop\$111.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_11.json) untuk mengatasi pola akses 10 (`getInvoiceByInvoiceId`) dan 11 (`getPaymentByInvoiceId`), keduanya terkait dengan. `invoice` Meskipun berbeda, dua pola akses ini direalisasikan menggunakan kondisi kunci yang sama. `Payments` didefinisikan sebagai atribut dengan jenis data peta pada entitas `invoice`.

**catatan**  
`GSI1-PK` dan `GSI1-SK` kelebihan beban untuk menyimpan informasi berbagai entitas sehingga beberapa pola akses dapat dilayani dari GSI yang sama. Untuk informasi selengkapnya tentang kelebihan beban GSI, lihat [Membebani Indeks Sekunder Global di DynamoDB](bp-gsi-overloading.md).

Untuk menangani pola akses 10 dan 11, lakukan kueri `GSI1` dengan `GSI1-PK=invoiceId` dan `GSI1-SK=invoiceId`.

**GSI1:**

![\[Desain GSI dengan invoiceID sebagai partisi dan kunci pengurutan untuk mendapatkan faktur dan pembayaran dengan ID faktur.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-10-Step9.png)


**Langkah 10: Tangani pola akses 12 (`getShipmentDetailsByShipmentId`) dan 13 (`getShipmentByWarehouseId`)**

Impor [AnOnlineShop\$112.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_12.json) untuk mengatasi pola akses 12 (`getShipmentDetailsByShipmentId`) dan 13 (). `getShipmentByWarehouseId` 

Perhatikan bahwa entitas `shipmentItem` ditambahkan ke koleksi item *pesanan* pada tabel dasar agar dapat mengambil semua detail tentang pesanan dalam satu operasi kueri.

**Tabel dasar:**

![\[Desain tabel dengan entitas ShipmentItem dalam koleksi item pesanan untuk mendapatkan semua detail pesanan.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-11-Step10.png)


Kunci `GSI1` partisi dan sortir telah digunakan untuk memodelkan one-to-many hubungan antara `shipment` dan`shipmentItem`. Untuk menangani pola akses 12 (`getShipmentDetailsByShipmentId`), lakukan kueri `GSI1` dengan `GSI1-PK=shipmentId` dan `GSI1-SK=shipmentId`.

**GSI1:**

![\[GSI1 desain dengan shipmentID sebagai partisi dan kunci sortir untuk mendapatkan detail pengiriman dengan ID pengiriman.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-12-Step10-GSI.png)


Kita perlu membuat GSI (`GSI2`) lain untuk memodelkan one-to-many hubungan baru antara `warehouse` dan `shipment` untuk pola akses 13 (`getShipmentByWarehouseId`). Untuk menangani pola akses ini, lakukan kueri `GSI2` dengan `GSI2-PK=warehouseId` dan `GSI2-SK begins_with “sh#”`.

**GSI2:**

![\[GSI2 desain dengan WarehouseID dan shipmentID sebagai partisi dan kunci sortir untuk mendapatkan pengiriman berdasarkan gudang.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-13-Step10-GSI2.png)


**Langkah 11: Tangani pola akses 14 (`getProductInventoryByWarehouseId`) 15 (`getInvoiceByCustomerIdForDateRange`), dan 16 (`getProductsByCustomerIdForDateRange`)**

Impor [AnOnlineShop\$113.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_13.json) untuk menambahkan data yang terkait dengan kumpulan pola akses berikutnya. Untuk menangani pola akses 14 (`getProductInventoryByWarehouseId`), lakukan kueri `GSI2` dengan `GSI2-PK=warehouseId` dan `GSI2-SK begins_with “p#”`.

**GSI2:**

![\[GSI2 desain dengan WarehouseID dan productID sebagai partisi dan kunci sortir untuk mengatasi pola akses 14.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-14-Step11-GSI2.png)


Untuk menangani pola akses 15 (`getInvoiceByCustomerIdForDateRange`), lakukan kueri `GSI2` dengan `GSI2-PK=customerId` dan `GSI2-SK between (i#date1, i#date2)`.

**GSI2:**

![\[GSI2 desain dengan CustomerID dan rentang tanggal faktur sebagai partisi dan kunci pengurutan untuk mengatasi pola akses 15.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-15-Step11-GSI2.png)


Untuk menangani pola akses 16 (`getProductsByCustomerIdForDateRange`), lakukan kueri `GSI2` dengan `GSI2-PK=customerId` dan `GSI2-SK between (p#date1, p#date2)`.

**GSI2:**

![\[GSI2 desain dengan CustomerID dan rentang tanggal produk sebagai partisi dan sortir kunci untuk mengatasi pola akses 16\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-16-Step11-GSI2.png)


**catatan**  
Di [NoSQL Workbench](workbench.md), *faset* mewakili pola akses data aplikasi yang berbeda untuk DynamoDB. Faset memberi Anda cara untuk melihat subset data dalam tabel tanpa harus melihat rekaman yang tidak memenuhi batasan faset. Faset dianggap sebagai alat pemodelan data visual, dan tidak ada sebagai konstruksi yang dapat digunakan di DynamoDB, karena aspek tersebut murni bantuan untuk memodelkan pola akses.   
Impor [AnOnlineShop\$1facets.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/an-online-shop/json/AnOnlineShop_facets.json) untuk melihat aspek untuk kasus penggunaan ini.

Semua pola akses dan bagaimana desain skema mengatasinya dirangkum dalam tabel di bawah ini:


| Pola akses | Basis table/GSI/LSI | Operasi | Nilai kunci partisi | Nilai kunci urutan | 
| --- | --- | --- | --- | --- | 
| getCustomerByCustomerId | Tabel dasar | GetItem |  PK=customerId | SK=customerId | 
| getProductByProductId | Tabel dasar | GetItem |  PK=productId | SK=productId | 
| getWarehouseByWarehouseId | Tabel dasar | GetItem |  PK=warehouseId | SK=warehouseId | 
| getProductInventoryByProductId | Tabel dasar | Kueri |  PK=productId | SK begins\$1with "w\$1" | 
| getOrderDetailsByOrderId | Tabel dasar | Kueri |  PK=orderId |  | 
| getProductByOrderId | Tabel dasar | Kueri |  PK=orderId | SK begins\$1with "p\$1" | 
| getInvoiceByOrderId |  Tabel dasar | Kueri |  PK=orderId | SK begins\$1with "i\$1" | 
| getShipmentByOrderId |  Tabel dasar | Kueri |  PK=orderId | SK begins\$1with "sh\$1" | 
| getOrderByProductIdForDateRange |  GSI1 | Kueri |  PK=productId | SK antara date1 dan date2 | 
| getInvoiceByInvoiceId |  GSI1 | Kueri |  PK=invoiceId | SK=invoiceId | 
| getPaymentByInvoiceId |  GSI1 | Kueri |  PK=invoiceId | SK=invoiceId | 
| getShipmentDetailsByShipmentId |  GSI1 | Kueri |  PK=shipmentId | SK=shipmentId | 
| getShipmentByWarehouseId |  GSI2 | Kueri |  PK=warehouseId | SK begins\$1with "sh\$1" | 
| getProductInventoryByWarehouseId |  GSI2 | Kueri |  PK=warehouseId | SK begins\$1with "p\$1" | 
| getInvoiceByCustomerIdForDateRange |  GSI2 | Kueri |  PK=customerId | SK antara i\$1date1 dan i\$1date2 | 
| getProductsByCustomerIdForDateRange |  GSI2 | Kueri |  PK=customerId | SK antara p\$1date1 dan p\$1date2 | 

### Skema akhir toko online
<a name="data-modeling-schema-online-store-final-schema"></a>

Berikut adalah desain skema akhir. [Untuk mengunduh desain skema ini sebagai file JSON, lihat DynamoDB Design Patterns on.](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/schema_design/SchemaExamples) GitHub

**Tabel dasar**

![\[Skema akhir tabel dasar untuk toko online dengan atribut, seperti EntityName dan Nama.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-17-Final-BaseTable.png)


**GSI1**

![\[GSI1 Skema akhir untuk tabel dasar toko online dengan atribut, seperti EntityType.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-18-Final-GSI1.png)


**GSI2**

![\[GSI2 Skema akhir untuk tabel dasar toko online dengan atribut, seperti EntityType.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/DataModeling/OnlineShop-19-Final-GSI2.png)


## Menggunakan NoSQL Workbench dengan desain skema ini
<a name="data-modeling-schema-online-shop-nosql"></a>

Anda dapat mengimpor skema akhir ini ke [NoSQL Workbench](workbench.md), sebuah alat visual yang menyediakan fitur pemodelan data, visualisasi data, dan pengembangan kueri untuk DynamoDB, guna mengeksplorasi dan mengedit proyek baru Anda lebih lanjut. Ikuti langkah-langkah berikut untuk memulai:

1. Unduh NoSQL Workbench. Untuk informasi selengkapnya, lihat [Unduh NoSQL Workbench untuk DynamoDB](workbench.settingup.md).

1. Unduh file skema JSON yang tercantum di atas, yang sudah dalam format model NoSQL Workbench.

1. Impor file skema JSON ke NoSQL Workbench. Untuk informasi selengkapnya, lihat [Mengimpor model data yang ada](workbench.Modeler.ImportExisting.md). 

1. Setelah mengimpor model data ke NoSQL Workbench, Anda dapat mengeditnya. Lihat informasi yang lebih lengkap di [Mengedit model data yang ada](workbench.Modeler.Edit.md).

# Praktik terbaik untuk memodelkan data relasional di DynamoDB
<a name="bp-relational-modeling"></a>

Bagian ini menyediakan praktik terbaik untuk memodelkan data relasional di Amazon DynamoDB. Pertama, kami memperkenalkan konsep pemodelan data tradisional. Kemudian, kami menjelaskan keuntungan menggunakan DynamoDB dibandingkan sistem manajemen basis data relasional tradisional—bagaimana DynamoDB menghilangkan kebutuhan untuk operasi JOIN dan mengurangi overhead. 

Kami kemudian menjelaskan cara menyusun tabel DynamoDB yang menskalakan secara efisien. Terakhir, kami memberikan contoh cara memodelkan data relasional di DynamoDB.

**Topics**
+ [Model basis data relasional traditional](#SQLtoNoSQL.relational-modeling2)
+ [Cara DynamoDB menghilangkan kebutuhan akan operasi JOIN](#bp-relational-modeling-joins)
+ [Bagaimana transaksi DynamoDB menghilangkan overhead ke proses tulis](#bp-relational-modeling-transactions)
+ [Langkah pertama untuk memodelkan data relasional di DynamoDB](bp-modeling-nosql.md)
+ [Contoh memodelkan data relasional di DynamoDB](bp-modeling-nosql-B.md)

## Model basis data relasional traditional
<a name="SQLtoNoSQL.relational-modeling2"></a>

Sistem manajemen basis data relasional tradisional (RDBMS) menyimpan data dalam struktur relasional yang dinormalisasi. Tujuan dari model data relasional adalah untuk mengurangi duplikasi data (melalui normalisasi) untuk mendukung integritas referensial dan mengurangi anomali data. 

Skema berikut adalah contoh dari model data relasional untuk penerapan urutan-entri generik. Penerapan ini mendukung skema sumber daya manusia yang mendukung sistem pendukung operasional dan bisnis dari produsen teoretis.

![\[Contoh skema RDBMS.\]](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/RDBMS.png)


Sebagai layanan basis data non-relasional, DynamoDB menawarkan banyak keunggulan dibandingkan sistem manajemen basis data relasional tradisional. 

## Cara DynamoDB menghilangkan kebutuhan akan operasi JOIN
<a name="bp-relational-modeling-joins"></a>

Sebuah RDBMS menggunakan bahasa kueri terstruktur (SQL) untuk mengembalikan data ke aplikasi. Karena normalisasi model data, kueri semacam ini biasanya memerlukan penggunaan operator `JOIN` untuk menggabungkan data dari satu atau beberapa tabel.

Misalnya, untuk menghasilkan daftar item pesanan pembelian yang diurutkan berdasarkan jumlah stok di semua gudang yang dapat mengirimkan setiap item, Anda bisa mengeluarkan kueri SQL berikut terhadap skema sebelumnya.

```
SELECT * FROM Orders
  INNER JOIN Order_Items ON Orders.Order_ID = Order_Items.Order_ID
  INNER JOIN Products ON Products.Product_ID = Order_Items.Product_ID
  INNER JOIN Inventories ON Products.Product_ID = Inventories.Product_ID
  ORDER BY Quantity_on_Hand DESC
```

Kueri SQL semacam ini dapat menyediakan API fleksibel untuk mengakses data, tetapi kueri tersebut membutuhkan pemrosesan dalam jumlah besar. Setiap gabungan dalam kueri meningkatkan kompleksitas runtime kueri karena data untuk setiap tabel harus ditahapkan dan kemudian dikumpulkan untuk mengembalikan set hasil. 

Faktor lain yang dapat memengaruhi durasi yang dibutuhkan untuk menjalankan kueri adalah ukuran tabel dan apakah kolom yang digabungkan memiliki indeks. Kueri sebelumnya memulai kueri kompleks di beberapa tabel, lalu mengurutkan set hasilnya.

Menghilangkan kebutuhan untuk `JOINs` adalah inti dari pemodelan data NoSQL. Inilah sebabnya kami membangun DynamoDB untuk mendukung Amazon.com, dan mengapa DynamoDB dapat memberikan performa yang konsisten di semua skala. Mengingat kompleksitas runtime dari kueri SQL dan`JOINs`, kinerja RDBMS tidak konstan pada skala. Hal ini menyebabkan masalah performa seiring berkembangnya aplikasi pelanggan.

Meskipun normalisasi data mengurangi jumlah data yang disimpan ke disk, sumber daya yang paling terkendala sehingga berdampak performa sering kali adalah waktu CPU dan latensi jaringan. 

DynamoDB dibangun untuk meminimalkan kendala tersebut dengan menghilangkan `JOINs` (dan mendorong denormalisasi data) dan mengoptimalkan arsitektur basis data untuk sepenuhnya menjawab kueri aplikasi dengan satu permintaan ke item. Kualitas ini memungkinkan DynamoDB untuk menghadirkan performa milidetik satu digit di semua skala. Ini karena kompleksitas runtime untuk operasi DynamoDB konstan, terlepas dari ukuran data, untuk pola akses umum.

## Bagaimana transaksi DynamoDB menghilangkan overhead ke proses tulis
<a name="bp-relational-modeling-transactions"></a>

Faktor lain yang dapat memperlambat RDBMS adalah penggunaan transaksi untuk menulis ke skema yang dinormalisasi. Seperti yang ditunjukkan dalam contoh, struktur data relasional yang digunakan oleh sebagian besar aplikasi pemrosesan transaksi online (OLTP) harus diuraikan dan didistribusikan ke beberapa tabel logis jika disimpan di RDBMS. 

Oleh karena itu, kerangka transaksi yang sesuai dengan ACID diperlukan untuk menghindari kondisi balapan dan masalah integritas data yang dapat terjadi jika aplikasi mencoba membaca objek yang sedang dalam proses penulisan. Kerangka transaksi semacam itu, jika digabungkan dengan skema relasional, dapat menambah overhead yang signifikan untuk proses tulis.

Implementasi transaksi di DynamoDB dapat mencegah masalah penskalaan umum yang dialami pada RDBMS. DynamoDB melakukannya dengan menerbitkan transaksi sebagai panggilan API tunggal dan membatasi jumlah item yang dapat diakses dalam transaksi tunggal tersebut. Transaksi yang berjalan lama dapat menyebabkan masalah operasional karena mengunci data dalam jangka waktu yang lama, atau terus-menerus, karena transaksi tidak pernah ditutup. 

Untuk mencegah masalah demikian di DynamoDB, transaksi diimplementasikan dengan dua operasi API yang berbeda: `TransactWriteItems` dan `TransactGetItems`. Operasi API ini tidak memiliki semantik awal dan akhir yang lazim di RDBMS. Selanjutnya, DynamoDB memiliki batas akses 100 item dalam transaksi untuk mencegah transaksi yang berjalan lama. Untuk mempelajari selengkapnya tentang transaksi DynamoDB, lihat [Bekerja dengan transaksi](transactions.md).

Dengan demikian, ketika bisnis Anda memerlukan respons latensi rendah terhadap kueri dengan lalu lintas tinggi, memanfaatkan sistem NoSQL umumnya masuk akal secara teknis dan ekonomis. Amazon DynamoDB membantu memecahkan masalah yang membatasi skalabilitas sistem relasional dengan menghindari masalah tersebut.

Performa RDBMS biasanya tidak menskalakan dengan baik karena alasan berikut:
+ Penggabungan yang mahal digunakan untuk mengumpulkan kembali tampilan yang diperlukan dari hasil kueri.
+ Sistem tersebut menormalkan data dan menyimpannya di beberapa tabel yang memerlukan sejumlah kueri untuk menulis ke disk.
+ Ini umumnya menimbulkan biaya performa sistem transaksi yang sesuai dengan ACID.

DynamoDB menskalakan dengan baik karena alasan berikut:
+ Fleksibilitas skema memungkinkan DynamoDB menyimpan data hierarkis kompleks dalam satu item.
+ Desain kunci komposit memungkinkan DynamoDB menyimpan item terkait secara berdekatan di tabel yang sama.
+ Transaksi dilakukan dalam satu operasi. Batas jumlah item yang dapat diakses adalah 100, untuk menghindari operasi yang berjalan lama.

Kueri terhadap penyimpanan data menjadi jauh lebih sederhana, sering kali dalam bentuk berikut:

```
SELECT * FROM Table_X WHERE Attribute_Y = "somevalue"
```

DynamoDB dapat memberikan data yang diminta dengan lebih efisien dibandingkan RDBMS dalam contoh sebelumnya.

# Langkah pertama untuk memodelkan data relasional di DynamoDB
<a name="bp-modeling-nosql"></a>

**catatan**  
Desain NoSQL membutuhkan pola pikir yang berbeda dari desain RDBMS. Untuk RDBMS, Anda dapat membuat model data yang dinormalisasi tanpa memikirkan pola akses. Anda kemudian dapat memperluasnya nanti ketika ada pertanyaan dan persyaratan kueri baru. Sebaliknya, di Amazon DynamoDB, Anda tidak boleh mulai merancang skema sampai Anda mengetahui pertanyaan-pertanyaan yang perlu dijawab. Memahami masalah bisnis dan kasus penggunaan aplikasi di awal sangatlah penting.

Untuk mulai merancang tabel DynamoDB yang akan menskalakan secara efisien, Anda harus melakukan beberapa langkah pertama untuk mengidentifikasi pola akses yang diperlukan oleh operasi dan sistem dukungan bisnis (OSS/BSS) yang memerlukan dukungan:
+ Untuk aplikasi baru, tinjau cerita pengguna tentang aktivitas dan sasaran. Dokumentasikan berbagai kasus penggunaan yang Anda identifikasi, dan analisis pola akses yang mereka butuhkan.
+ Untuk aplikasi yang sudah ada, analisis log kueri untuk mengetahui bagaimana orang-orang saat ini menggunakan sistem tersebut dan apa pola akses utamanya.

Setelah menyelesaikan proses ini, Anda akan mendapatkan daftar seperti berikut.


**Pola Akses untuk Aplikasi Entri Pesanan**  

| Pola \$1 | Deskripsi Pola Akses | 
| --- | --- | 
| 1 | Cari Detail Karyawan berdasarkan ID Karyawan | 
| 2 | Kueri Detail Karyawan berdasarkan Nama Karyawan | 
| 3 | Temukan Nomor Telepon Karyawan | 
| 4 | Temukan Nomor Telepon Pelanggan | 
| 5 | Dapatkan Pesanan untuk Pelanggan dalam Rentang Tanggal | 
| 6 | Tampilkan semua Pesanan Terbuka dalam Rentang Tanggal | 
| 7 | Lihat semua Karyawan yang dipekerjakan baru-baru ini | 
| 8 | Temukan Semua Karyawan di Gudang | 
| 9 | Dapatkan semua Item sesuai Pesanan untuk Produk | 
| 10 | Dapatkan Inventaris Produk di Semua Gudang | 
| 11 | Dapatkan Pelanggan dengan Perwakilan Akun | 
| 12 | Dapatkan Pesanan berdasarkan Akun Rep | 
| 13 | Dapatkan Karyawan dengan Job Title | 
| 14 | Dapatkan Inventaris berdasarkan Produk dan Gudang | 
| 15 | Dapatkan Total Inventaris Produk | 

Dalam aplikasi yang sebenarnya, daftar Anda mungkin lebih panjang. Namun, kumpulan ini menunjukkan berbagai kompleksitas pola kueri yang mungkin Anda temukan di lingkungan produksi.

Pendekatan modern untuk desain skema DynamoDB menggunakan prinsip berorientasi agregat, mengelompokkan data berdasarkan pola akses daripada batas entitas yang kaku. Pendekatan ini mempertimbangkan beberapa pola desain:
+ *Desain Tabel Tunggal* - Menggunakan kunci pengurutan komposit, indeks sekunder global yang kelebihan beban, dan pola daftar kedekatan untuk menyimpan beberapa jenis entitas dalam satu tabel
+ *Desain Multi-Tabel* - Menggunakan tabel terpisah untuk entitas dengan karakteristik operasional independen dan korelasi akses rendah, dengan strategis GSIs untuk kueri lintas entitas
+ *Desain Agregat* - Menyematkan data terkait saat selalu diakses bersama (Pesanan \$1 OrderItems) atau menggunakan koleksi item untuk mengidentifikasi hubungan (Product \$1 Inventory)

Pilihan antara pendekatan ini tergantung pada pola akses spesifik Anda, karakteristik data, dan persyaratan operasional. Anda dapat menggunakan elemen-elemen ini untuk mengatur data sehingga aplikasi dapat mengambil apa pun yang dibutuhkannya untuk pola akses tertentu menggunakan satu kueri pada tabel atau indeks.

**catatan**  
Pilihan antara desain single-table dan multi-table tergantung pada kebutuhan spesifik Anda. Desain meja tunggal bekerja dengan baik ketika entitas memiliki korelasi akses tinggi dan karakteristik operasional yang serupa. Desain multi-tabel lebih disukai ketika entitas memiliki persyaratan operasional independen, pola akses yang berbeda, atau ketika Anda membutuhkan batasan operasional yang jelas. Contoh dalam panduan ini menunjukkan pendekatan multi-tabel dengan agregasi strategis dan denormalisasi.

Untuk menggunakan NoSQL Workbench untuk DynamoDB guna membantu memvisualisasikan desain kunci partisi Anda, lihat [Membangun Model Data dengan NoSQL Workbench](workbench.Modeler.md).

# Contoh memodelkan data relasional di DynamoDB
<a name="bp-modeling-nosql-B"></a>

Contoh ini menjelaskan cara memodelkan data relasional di Amazon DynamoDB. Desain tabel DynamoDB sesuai dengan skema entri urutan relasional yang ditampilkan di. [Pemodelan relasional](bp-relational-modeling.md) Desain ini menggunakan beberapa tabel khusus daripada daftar kedekatan tunggal, memberikan batasan operasional yang jelas sambil memanfaatkan strategi GSIs untuk melayani semua pola akses secara efisien.

Pendekatan desain menggunakan prinsip berorientasi agregat, mengelompokkan data berdasarkan pola akses daripada batas entitas yang kaku. Keputusan desain utama termasuk menggunakan tabel terpisah untuk entitas dengan korelasi akses rendah, menyematkan data terkait saat selalu diakses bersama, dan menggunakan koleksi item untuk mengidentifikasi hubungan.

Tabel berikut dan indeks yang menyertainya mendukung skema entri urutan relasional:

## Desain Meja Karyawan
<a name="employee-table-design"></a>

Tabel Karyawan menyimpan informasi karyawan sebagai satu entitas per item, dioptimalkan untuk pencarian karyawan langsung dan mendukung beberapa pola kueri melalui strategi. GSIs Tabel ini menunjukkan prinsip merancang tabel terpisah untuk entitas dengan karakteristik operasional independen dan korelasi akses lintas entitas yang rendah.

Tabel menggunakan kunci partisi sederhana (employee\$1id) tanpa kunci pengurutan, karena setiap karyawan adalah entitas yang berbeda. Empat GSIs memungkinkan kueri yang efisien dengan atribut yang berbeda:
+ *EmployeeByName GSI* - Menggunakan proyeksi INCLUDE dengan semua atribut karyawan untuk mendukung pengambilan detail karyawan lengkap berdasarkan nama, menangani nama duplikat potensial dengan employee\$1id sebagai kunci pengurutan
+ *EmployeeByWarehouse GSI* - Menggunakan proyeksi INCLUDE dengan hanya atribut penting (name, job\$1title, hire\$1date) untuk meminimalkan biaya penyimpanan sambil mendukung kueri berbasis gudang
+ *EmployeeByJobTitle GSI* - Mengaktifkan kueri berbasis peran dengan proyeksi INCLUDE untuk pelaporan dan analisis organisasi
+ *EmployeeByHireDate GSI* - Menggunakan nilai kunci partisi statis “EMPLOYEE” dengan hire\$1date sebagai kunci pengurutan untuk mengaktifkan kueri rentang tanggal yang efisien untuk perekrutan terbaru. Karena karyawan additions/updates biasanya di bawah 1.000 WCU, satu partisi dapat menangani beban tulis tanpa masalah partisi panas


**Meja Karyawan - Struktur Meja Dasar**  

| karyawan\$1id (PK) | name | phone\$1numbers | gudang\$1id | job\$1title | hire\$1date | entity\$1type | 
| --- | --- | --- | --- | --- | --- | --- | 
| emp\$1001 | John Smith | ["\$11-555-0101"] | wh\$1laut | pengelola | 2024-03-15 | KARYAWAN | 
| emp\$1002 | Jane Doe | ["\$11-555-0102", “\$11-555-0103"] | wh\$1laut | Rekanan | 2025-01-10 | KARYAWAN | 
| emp\$1003 | Bob Wilson | ["\$11-555-0104"] | wh\$1pdx | Rekanan | 2025-06-20 | KARYAWAN | 
| emp\$1004 | Alice Coklat | ["\$11-555-0105"] | wh\$1pdx | Pengawas | 2023-11-05 | KARYAWAN | 
| emp\$1005 | Charlie Davis | ["\$11-555-0106"] | wh\$1laut | Rekanan | 2025-12-01 | KARYAWAN | 


**EmployeeByName GSI - Mendukung Pertanyaan Nama Karyawan**  

| nama (GSI-PK) | karyawan\$1id (GSI-SK) | phone\$1numbers | gudang\$1id | job\$1title | hire\$1date | 
| --- | --- | --- | --- | --- | --- | 
| Alice Coklat | emp\$1004 | ["\$11-555-0105"] | wh\$1pdx | Pengawas | 2023-11-05 | 
| Bob Wilson | emp\$1003 | ["\$11-555-0104"] | wh\$1pdx | Rekanan | 2025-06-20 | 
| Charlie Davis | emp\$1005 | ["\$11-555-0106"] | wh\$1laut | Rekanan | 2025-12-01 | 
| Jane Doe | emp\$1002 | ["\$11-555-0102", “\$11-555-0103"] | wh\$1laut | Rekanan | 2025-01-10 | 
| John Smith | emp\$1001 | ["\$11-555-0101"] | wh\$1laut | pengelola | 2024-03-15 | 


**EmployeeByWarehouse GSI - Mendukung Pertanyaan Gudang**  

| gudang\$1id (GSI-PK) | karyawan\$1id (GSI-SK) | name | job\$1title | hire\$1date | 
| --- | --- | --- | --- | --- | 
| wh\$1pdx | emp\$1003 | Bob Wilson | Rekanan | 2025-06-20 | 
| wh\$1pdx | emp\$1004 | Alice Coklat | Pengawas | 2023-11-05 | 
| wh\$1laut | emp\$1001 | John Smith | pengelola | 2024-03-15 | 
| wh\$1laut | emp\$1002 | Jane Doe | Rekanan | 2025-01-10 | 
| wh\$1laut | emp\$1005 | Charlie Davis | Rekanan | 2025-12-01 | 


**EmployeeByJobTitle GSI - Mendukung Pertanyaan Judul Pekerjaan**  

| job\$1title (GSI-PK) | karyawan\$1id (GSI-SK) | name | gudang\$1id | hire\$1date | 
| --- | --- | --- | --- | --- | 
| Rekanan | emp\$1002 | Jane Doe | wh\$1laut | 2025-01-10 | 
| Rekanan | emp\$1003 | Bob Wilson | wh\$1pdx | 2025-06-20 | 
| Rekanan | emp\$1005 | Charlie Davis | wh\$1laut | 2025-12-01 | 
| pengelola | emp\$1001 | John Smith | wh\$1laut | 2024-03-15 | 
| Supervisor | emp\$1004 | Alice Coklat | wh\$1pdx | 2023-11-05 | 


**EmployeeByHireDate GSI - Mendukung Pertanyaan Sewa Terbaru**  

| entity\$1type (GSI-PK) | hire\$1date (GSI-SK) | karyawan\$1id | name | gudang\$1id | 
| --- | --- | --- | --- | --- | 
| KARYAWAN | 2023-11-05 | emp\$1004 | Alice Coklat | wh\$1pdx | 
| KARYAWAN | 2024-03-15 | emp\$1001 | John Smith | wh\$1laut | 
| KARYAWAN | 2025-01-10 | emp\$1002 | Jane Doe | wh\$1laut | 
| KARYAWAN | 2025-06-20 | emp\$1003 | Bob Wilson | wh\$1pdx | 
| KARYAWAN | 2025-12-01 | emp\$1005 | Charlie Davis | wh\$1laut | 

## Desain Meja Pelanggan
<a name="customer-table-design"></a>

Tabel Pelanggan menyimpan informasi pelanggan dengan denormalisasi strategis account\$1rep\$1id untuk mengaktifkan kueri perwakilan akun yang efisien. Pilihan desain ini memperdagangkan sedikit overhead penyimpanan untuk kinerja kueri, menghilangkan kebutuhan untuk bergabung antara data pelanggan dan perwakilan akun.

Tabel mendukung beberapa nomor telepon per pelanggan menggunakan atribut list, menunjukkan fleksibilitas skema DynamoDB. GSI tunggal memungkinkan alur kerja perwakilan akun:
+ *CustomerByAccountRep GSI* - Menggunakan proyeksi INCLUDE dengan atribut nama dan email untuk mendukung manajemen pelanggan perwakilan akun tanpa memerlukan pengambilan catatan pelanggan penuh


**Tabel Pelanggan - Struktur Tabel Dasar**  

| customer\$1id (PK) | name | phone\$1numbers | Email | account\$1rep\$1id | 
| --- | --- | --- | --- | --- | 
| cust\$1001 | Acme Corp | ["\$11-555-1001"] | contact@acme.com | rep\$1001 | 
| cust\$1002 | TechStart Inc | ["\$11-555-1002", “\$11-555-1003"] | info@techstart.com | rep\$1001 | 
| cust\$1003 | Pedagang Global | ["\$11-555-1004"] | sales@globaltraders.com | rep\$1002 | 
| cust\$1004 | BuildRight LLC | ["\$11-555-1005"] | orders@buildright.com | rep\$1002 | 
| cust\$1005 | FastShip Co | ["\$11-555-1006"] | support@fastship.com | rep\$1003 | 


**CustomerByAccountRep GSI - Mendukung Pertanyaan Perwakilan Akun**  

| account\$1rep\$1id (GSI-PK) | customer\$1id (GSI-SK) | name | Email | 
| --- | --- | --- | --- | 
| rep\$1001 | cust\$1001 | Acme Corp | contact@acme.com | 
| rep\$1001 | cust\$1002 | TechStart Inc | info@techstart.com | 
| rep\$1002 | cust\$1003 | Pedagang Global | sales@globaltraders.com | 
| rep\$1002 | cust\$1004 | BuildRight LLC | orders@buildright.com | 
| rep\$1003 | cust\$1005 | FastShip Co | support@fastship.com | 

## Desain Tabel Pesanan
<a name="order-table-design"></a>

Tabel Order menggunakan partisi vertikal dengan item terpisah untuk header pesanan dan item pesanan. Desain ini memungkinkan kueri berbasis produk yang efisien sambil mempertahankan semua komponen pesanan dalam partisi yang sama untuk akses yang efisien. Setiap pesanan terdiri dari beberapa item:
+ *Order Header* - Berisi metadata pesanan dengan PK=Order\$1ID, SK = Order\$1ID
+ *Item Pesanan - Item* baris individu dengan PK=ORDER\$1ID, SK=PRODUCT\$1ID, memungkinkan kueri produk langsung

**catatan**  
Pendekatan partisi vertikal ini memperdagangkan kesederhanaan item pesanan tertanam untuk meningkatkan fleksibilitas kueri. Setiap item pesanan menjadi item DynamoDB terpisah, memungkinkan kueri berbasis produk yang efisien sambil mempertahankan semua data pesanan dalam partisi yang sama untuk pengambilan yang efisien dalam satu permintaan.

Tabel ini mencakup denormalisasi strategis account\$1rep\$1id (digandakan dari tabel Pelanggan) untuk mengaktifkan kueri perwakilan akun langsung tanpa memerlukan pencarian pelanggan. Untuk skenario penulisan throughput tinggi, pesanan OPEN menyertakan atribut status dan pecahan untuk mengaktifkan sharding tulis di beberapa partisi.

Empat GSIs mendukung pola kueri yang berbeda dengan proyeksi yang dioptimalkan:
+ *OrderByCustomerDate GSI* - Menggunakan proyeksi INCLUDE dengan ringkasan pesanan dan detail item untuk mendukung riwayat pesanan pelanggan dengan pemfilteran rentang tanggal
+ *OpenOrdersByDate GSI (Sparse, Sharded)* - Menggunakan kunci partisi multi-atribut (status\$1pecahan) dengan 5 pecahan untuk mendistribusikan 5.000 WPS (menulis per detik) di seluruh partisi (masing-masing 1.000 WPS, cocok dengan 1.000 WCU DynamoDB per batas partisi). Hanya indeks OPEN order (20% dari total), yang dapat membantu mengurangi biaya penyimpanan GSI. Memerlukan query paralel di semua 5 pecahan dengan penggabungan hasil sisi klien
+ *OrderByAccountRep GSI* - Menggunakan proyeksi INCLUDE dengan atribut ringkasan pesanan untuk mendukung alur kerja perwakilan akun tanpa detail pesanan lengkap
+ *ProductInOrders GSI* - Dibuat dari OrderItem catatan (PK=ORDER\$1ID, SK=PRODUCT\$1ID), GSI ini memungkinkan kueri untuk menemukan semua pesanan yang berisi produk tertentu. Menggunakan proyeksi INCLUDE dengan konteks pesanan (customer\$1id, order\$1date, quantity) untuk analisis permintaan produk


**Tabel Pesanan - Struktur Tabel Dasar (Partisi Vertikal)**  

| PK | SK | customer\$1id | pesanan\$1tanggal | status | account\$1rep\$1id | kuantitas | price | serpihan | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| ord\$1001 | ord\$1001 | cust\$1001 | 2025-11-15 | TERTUTUP | rep\$1001 |  |  |  | 
| ord\$1001 | prod\$1100 |  |  |  |  | 5 | 25.00 |  | 
| ord\$1002 | ord\$1002 | cust\$1001 | 2025-12-20 | BUKA | rep\$1001 |  |  | 0 | 
| ord\$1002 | prod\$1101 |  |  |  |  | 10 | 15.00 |  | 
| ord\$1003 | ord\$1003 | cust\$1002 | 2026-01-05 | BUKA | rep\$1001 |  |  | 2 | 
| ord\$1003 | prod\$1100 |  |  |  |  | 3 | 25.00 |  | 


**OrderByCustomerDate GSI - Mendukung Pertanyaan Pesanan Pelanggan**  

| customer\$1id (GSI-PK) | pesanan\$1tanggal (GSI-SK) | order\$1id | status | total\$1amount | pesanan\$1item | serpihan | 
| --- | --- | --- | --- | --- | --- | --- | 
| cust\$1001 | 2025-11-15 | ord\$1001 | TERTUTUP | 225.00 | [\$1product\$1id: “prod\$1100", jumlah: 5\$1] |  | 
| cust\$1001 | 2025-12-20 | ord\$1002 | BUKA | 150.00 | [\$1product\$1id: “prod\$1101", jumlah: 10\$1] | 0 | 
| cust\$1002 | 2026-01-05 | ord\$1003 | BUKA | 175.00 | [\$1product\$1id: “prod\$1100", jumlah: 3\$1] | 2 | 
| cust\$1003 | 2025-10-10 | ord\$1004 | TERTUTUP | 250.00 | [\$1product\$1id: “prod\$1101", jumlah: 5\$1] |  | 
| cust\$1004 | 2026-01-03 | ord\$1005 | BUKA | 200.00 | [\$1product\$1id: “prod\$1100", jumlah: 20\$1] | 1 | 


**OpenOrdersByDate GSI (Sparse, Sharded) - Mendukung Kueri Pesanan Terbuka Throughput Tinggi**  

| status (GSI-PK-1) | pecahan (GSI-PK-2) | pesanan\$1tanggal (SK) | order\$1id | customer\$1id | account\$1rep\$1id | pesanan\$1item | total\$1amount | 
| --- | --- | --- | --- | --- | --- | --- | --- | 
| BUKA | 0 | 2025-12-20 | ord\$1002 | cust\$1001 | rep\$1001 | [\$1product\$1id: “prod\$1101", jumlah: 10\$1] | 150.00 | 
| BUKA | 1 | 2026-01-03 | ord\$1005 | cust\$1004 | rep\$1002 | [\$1product\$1id: “prod\$1100", jumlah: 20\$1] | 200.00 | 
| BUKA | 2 | 2026-01-05 | ord\$1003 | cust\$1002 | rep\$1001 | [\$1product\$1id: “prod\$1100", jumlah: 3\$1] | 175.00 | 


**OrderByAccountRep GSI - Mendukung Kueri Pesanan Perwakilan Akun**  

| account\$1rep\$1id (GSI-PK) | pesanan\$1tanggal (GSI-SK) | order\$1id | customer\$1id | status | total\$1amount | 
| --- | --- | --- | --- | --- | --- | 
| rep\$1001 | 2025-11-15 | ord\$1001 | cust\$1001 | TERTUTUP | 225.00 | 
| rep\$1001 | 2025-12-20 | ord\$1002 | cust\$1001 | BUKA | 150.00 | 
| rep\$1001 | 2026-01-05 | ord\$1003 | cust\$1002 | BUKA | 175.00 | 
| rep\$1002 | 2025-10-10 | ord\$1004 | cust\$1003 | TERTUTUP | 250.00 | 
| rep\$1002 | 2026-01-03 | ord\$1005 | cust\$1004 | BUKA | 200.00 | 


**ProductInOrders GSI - Mendukung Pertanyaan Pesanan Produk**  

| product\$1id (GSI-PK) | order\$1id (GSI-SK) | customer\$1id | pesanan\$1tanggal | kuantitas | 
| --- | --- | --- | --- | --- | 
| prod\$1100 | ord\$1001 | cust\$1001 | 2025-11-15 | 5 | 
| prod\$1100 | ord\$1003 | cust\$1002 | 2026-01-05 | 3 | 
| prod\$1101 | ord\$1002 | cust\$1001 | 2025-12-20 | 10 | 

## Desain Meja Produk
<a name="product-table-design"></a>

Tabel Produk menggunakan pola pengumpulan item untuk menyimpan metadata produk dan data inventaris dalam partisi yang sama. Desain ini memanfaatkan hubungan identifikasi antara produk dan inventaris - inventaris tidak dapat ada tanpa produk induk. Menggunakan PK=PRODUCT\$1ID dengan SK=PRODUCT\$1ID untuk metadata produk dan SK=Warehouse\$1ID untuk item inventaris menghilangkan kebutuhan akan tabel Inventaris terpisah dan GSI, mengurangi biaya sekitar 50%.

Pola ini memungkinkan kueri yang efisien untuk inventaris gudang individu (GetItem dengan kunci komposit) dan semua inventaris gudang untuk suatu produk (Kueri pada kunci partisi). Atribut total\$1inventory dalam item metadata produk menyediakan agregasi denormalisasi untuk pencarian inventaris total cepat.


**Tabel Produk - Struktur Tabel Dasar (Pola Koleksi Item)**  

| product\$1id (PK) | gudang\$1id (SK) | product\$1name | kategori | unit\$1price | inventaris\$1kuantitas | total\$1inventaris | 
| --- | --- | --- | --- | --- | --- | --- | 
| prod\$1100 | prod\$1100 | Widget A | Hardware | 25.00 |  | 500 | 
| prod\$1100 | wh\$1laut |  |  |  | 200 |  | 
| prod\$1100 | wh\$1pdx |  |  |  | 150 |  | 
| prod\$1100 | wh\$1atl |  |  |  | 150 |  | 
| prod\$1101 | prod\$1101 | Gadget B | Elektronik | 50,00 |  | 300 | 
| prod\$1101 | wh\$1laut |  |  |  | 100 |  | 
| prod\$1101 | wh\$1pdx |  |  |  | 200 |  | 

Setiap tabel dirancang dengan Global Secondary Indexes (GSIs) khusus untuk mendukung pola akses yang diperlukan secara efisien. Desain menggunakan prinsip-prinsip berorientasi agregat dengan denormalisasi strategis dan pengindeksan jarang untuk mengoptimalkan kinerja dan biaya.

Optimalisasi desain utama meliputi:
+ *Sparse GSI* - OpenOrdersByDate hanya mengindeks pesanan OPEN (20% dari total), yang dapat membantu mengurangi biaya penyimpanan GSI
+ *Pola Koleksi Item* - Tabel produk menyimpan inventaris menggunakan PK=PRODUCT\$1ID, SK=Warehouse\$1ID untuk menghilangkan tabel inventaris terpisah
+ *Pesanan \$1 OrderItems Agregasi* - Tertanam sebagai item tunggal karena korelasi akses 100%
+ *Denormalisasi Strategis* - account\$1rep\$1id diduplikasi dalam tabel Order untuk kueri yang efisien

Terakhir, Anda dapat meninjau kembali pola akses yang ditetapkan sebelumnya. Tabel berikut menunjukkan bagaimana setiap pola akses didukung secara efisien menggunakan desain multi-tabel dengan strategis GSIs. Setiap pola menggunakan pencarian kunci langsung atau kueri GSI tunggal, menghindari pemindaian mahal dan memberikan kinerja yang konsisten pada skala apa pun.


| S. Tidak. | Pola akses | Ketentuan kueri | 
| --- | --- | --- | 
|  1  |  Cari Detail Karyawan berdasarkan ID Karyawan  |  Tabel Karyawan: GetItem (employee\$1id="emp\$1001")  | 
|  2  |  Kueri Detail Karyawan berdasarkan Nama Karyawan  |  EmployeeByName GSI: Kueri (name="John Smith”)  | 
|  3  |  Temukan Nomor Telepon Karyawan  |  Tabel Karyawan: GetItem (employee\$1id="emp\$1001")  | 
|  4  |  Temukan Nomor Telepon Pelanggan  |  Tabel Pelanggan: GetItem (customer\$1id = “cust\$1001")  | 
|  5  |  Dapatkan Pesanan untuk Pelanggan dalam Rentang Tanggal  |  OrderByCustomerDate GSI: Kueri (customer\$1id="cust\$1001", order\$1date ANTARA “2025-01-01" DAN “2025-12-31")  | 
|  6  |  Tampilkan semua Pesanan Terbuka dalam Rentang Tanggal  |  OpenOrdersByDate GSI: Kueri 5 pecahan secara paralel dengan PK multi-atribut (status="Open” \$1 shard=0-4), SK=ORDER\$1DATE ANTARA “2025-01-01" DAN “2025-12-31", gabungkan hasil  | 
|  7  |  Lihat semua Karyawan yang dipekerjakan baru-baru ini  |  EmployeeByHireDate GSI: Kueri (ENTITY\$1TYPE = “Karyawan”, hire\$1date >= “2025-01-01")  | 
|  8  |  Temukan Semua Karyawan di Gudang  |  EmployeeByWarehouse GSI: Kueri (warehouse\$1id="wh\$1sea”)  | 
|  9  |  Dapatkan semua Item sesuai Pesanan untuk Produk  |  ProductInOrders GSI: Kueri (product\$1id="prod\$1100")  | 
|  10  |  Dapatkan Inventaris Produk di Semua Gudang  |  Tabel Produk: Query (product\$1id = “prod\$1100")  | 
|  11  |  Dapatkan Pelanggan dengan Perwakilan Akun  |  CustomerByAccountRep GSI: Kueri (account\$1rep\$1id="rep\$1001")  | 
|  12  |  Dapatkan Pesanan berdasarkan Akun Rep  |  OrderByAccountRep GSI: Kueri (account\$1rep\$1id="rep\$1001")  | 
|  13  |  Dapatkan Karyawan dengan Job Title  |  EmployeeByJobTitle GSI: Kueri (job\$1title="Manajer”)  | 
|  14  |  Dapatkan Inventaris berdasarkan Produk dan Gudang  |  Tabel Produk: GetItem (product\$1id = “prod\$1100", warehouse\$1id = “wh\$1sea”)  | 
|  15  |  Dapatkan Total Inventaris Produk  |  Tabel Produk: GetItem (product\$1id = “prod\$1100", warehouse\$1id = “prod\$1100")  | 