

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

# Menggunakan Indeks Sekunder Global untuk kueri agregasi terwujud di DynamoDB
<a name="bp-gsi-aggregation"></a>

Mempertahankan metrik kunci dan agregasi yang mendekati waktu nyata selain data yang berubah dengan cepat menjadi semakin berharga bagi bisnis untuk mengambil keputusan dengan cepat. Misalnya, perpustakaan musik mungkin ingin menampilkan lagu-lagu yang paling banyak diunduh dalam waktu nyaris nyata, atau platform e-commerce mungkin perlu menampilkan produk yang sedang tren berdasarkan kategori.

Karena DynamoDB tidak mendukung operasi agregasi secara native `SUM` seperti `COUNT` atau di seluruh item, menghitung nilai-nilai ini pada waktu baca akan memerlukan pemindaian sejumlah besar item—yang mungkin lambat dan mahal. Sebagai gantinya, Anda dapat *menghitung agregasi terlebih dahulu* saat data berubah dan menyimpan hasilnya sebagai item biasa di tabel Anda. Pola ini disebut *agregasi terwujud*.

**Topics**
+ [Contoh skenario dan pola akses](#bp-gsi-aggregation-scenario)
+ [Mengapa agregasi pra-komputasi](#bp-gsi-aggregation-why)
+ [Desain tabel](#bp-gsi-aggregation-table-design)
+ [Pipa agregasi dengan Streams dan AWS Lambda](#bp-gsi-aggregation-pipeline)
+ [Desain GSI jarang](#bp-gsi-aggregation-sparse-gsi)
+ [Menanyakan GSI](#bp-gsi-aggregation-querying)
+ [Pertimbangan-pertimbangan](#bp-gsi-aggregation-considerations)

## Contoh skenario dan pola akses
<a name="bp-gsi-aggregation-scenario"></a>

Pertimbangkan aplikasi perpustakaan musik dengan persyaratan berikut:
+ Aplikasi ini merekam unduhan lagu individual pada volume tinggi (ribuan per detik).
+ Pengguna perlu melihat lagu yang paling banyak diunduh untuk bulan tertentu dengan latensi milidetik satu digit.
+ Aplikasi ini juga perlu mendukung pertanyaan seperti “10 lagu teratas bulan ini” dan “semua lagu yang diunduh pada bulan tertentu.”

Menghitung jumlah unduhan pada waktu baca dengan memindai semua catatan unduhan mungkin mahal pada skala ini. Sebagai gantinya, Anda dapat mempertahankan hitungan berjalan yang diperbarui saat setiap unduhan terjadi, dan menyimpannya dengan cara yang mendukung kueri yang efisien.

## Mengapa agregasi pra-komputasi
<a name="bp-gsi-aggregation-why"></a>

Ada beberapa pendekatan untuk komputasi agregasi. Tabel berikut membandingkan alternatif umum dan menjelaskan mengapa agregasi terwujud dalam DynamoDB seringkali paling cocok untuk jenis kasus penggunaan ini.


| Pendekatan | Pengorbanan | Kapan harus digunakan | 
| --- | --- | --- | 
| Pindai dan hitung pada waktu baca | Membutuhkan membaca semua catatan unduhan untuk setiap kueri. Latensi tumbuh dengan volume data dan mengkonsumsi kapasitas baca yang signifikan. | Hanya cocok untuk kumpulan data yang sangat kecil di mana latensi tidak menjadi perhatian. | 
| Toko agregasi eksternal (misalnya, Amazon ElastiCache) | Menambahkan kompleksitas operasional dengan layanan terpisah untuk dikelola. Membutuhkan logika sinkronisasi antara DynamoDB dan cache. | Ketika Anda membutuhkan pembacaan sub-milidetik atau logika agregasi kompleks yang melampaui hitungan sederhana. | 
| Application-level agregasi saat menulis | Memasangkan logika agregasi ke jalur tulis. Jika aplikasi gagal setelah merekam unduhan tetapi sebelum memperbarui hitungan, agregasi menjadi tidak konsisten. | Saat Anda membutuhkan agregasi yang sinkron dan sangat konsisten dan dapat mentolerir latensi penulisan tambahan. | 
| Agregasi terwujud dengan Streams dan Lambda | Memisahkan agregasi dari jalur tulis. Agregasi pada akhirnya konsisten (biasanya beberapa detik di belakang). Menambahkan biaya pemanggilan Lambda. | Ketika Anda membutuhkan agregasi mendekati waktu nyata dengan latensi baca rendah dan dapat mentolerir konsistensi akhirnya. Ini adalah pendekatan yang dijelaskan di halaman ini. | 

Pendekatan agregasi terwujud membuat jalur penulisan tetap sederhana (cukup rekam unduhan), menurunkan agregasi ke proses asinkron, dan menyimpan hasilnya di DynamoDB di mana ia dapat ditanyakan dengan latensi milidetik satu digit.

## Desain tabel
<a name="bp-gsi-aggregation-table-design"></a>

Desain ini menggunakan tabel tunggal dengan dua jenis item yang berbagi kunci partisi yang sama (`songID`) tetapi menggunakan pola kunci pengurutan yang berbeda untuk membedakannya:
+ **Unduh catatan** - Acara unduhan individu. Kunci sortir adalah `DownloadID` (pengidentifikasi unik untuk setiap unduhan).
+ **Item agregasi bulanan** — jumlah Pre-computed unduhan per lagu per bulan. Kunci sortir adalah bulan dalam `YYYY-MM` format (misalnya,`2018-01`). Item ini juga berisi `DownloadCount` atribut dengan total berjalan.

Hanya item agregasi bulanan yang berisi `Month` atribut. Perbedaan ini penting untuk desain GSI jarang yang dijelaskan nanti.

Diagram berikut menunjukkan tata letak tabel dengan kedua jenis item:

![Tata letak tabel perpustakaan musik yang menampilkan catatan unduhan dan item agregasi bulanan yang berbagi kunci partisi yang sama (sonGID).](http://docs.aws.amazon.com/id_id/amazondynamodb/latest/developerguide/images/AggregationQueries.png)



| Tipe barang | Kunci partisi (sonGID) | Sortir kunci | Atribut tambahan | 
| --- | --- | --- | --- | 
| Unduh catatan | song1 | download-abc123 | UserID, Timestamp | 
| Agregasi bulanan | song1 | 2018-01 | Month=2018-01, DownloadCount=1,746,992 | 

## Pipa agregasi dengan Streams dan AWS Lambda
<a name="bp-gsi-aggregation-pipeline"></a>

Pipa agregasi berfungsi sebagai berikut:

1. Ketika sebuah lagu diunduh, aplikasi menulis item baru ke meja dengan `Partition-Key=songID` dan`Sort-Key=DownloadID`.

1. DynamoDB Streams menangkap penulisan ini sebagai catatan aliran.

1. Fungsi Lambda, yang dilampirkan ke aliran, memproses catatan baru. Ini mengidentifikasi `songID` dan bulan berjalan, kemudian memperbarui item agregasi bulanan yang sesuai dengan menambah atribut. `DownloadCount`

1. Item agregasi yang diperbarui kemudian tersedia untuk kueri melalui GSI yang jarang.

Fungsi Lambda menggunakan `UpdateItem` panggilan dengan `ADD` ekspresi untuk meningkatkan jumlah unduhan secara atom. Ini menghindari kondisi balapan baca-modify-tulis:

```
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('MusicLibrary')

def handler(event, context):
    for record in event['Records']:
        if record['eventName'] == 'INSERT':
            new_image = record['dynamodb']['NewImage']
            song_id = new_image['songID']['S']
            # Derive the month from the download timestamp
            timestamp = new_image['Timestamp']['S']
            month = timestamp[:7]  # Extract YYYY-MM

            table.update_item(
                Key={
                    'songID': song_id,
                    'SK': month
                },
                UpdateExpression='ADD DownloadCount :inc SET #m = :month',
                ExpressionAttributeNames={
                    '#m': 'Month'
                },
                ExpressionAttributeValues={
                    ':inc': 1,
                    ':month': month
                }
            )
```

**catatan**  
Jika eksekusi Lambda gagal setelah menulis nilai agregasi yang diperbarui, catatan aliran dapat dicoba ulang. *Karena `ADD` operasi menambah hitungan setiap kali dijalankan, percobaan ulang akan menambah hitungan lebih dari sekali untuk unduhan yang sama, meninggalkan Anda dengan nilai perkiraan.* Untuk sebagian besar kasus penggunaan analitik dan papan peringkat, margin kesalahan kecil ini dapat diterima. Jika Anda memerlukan jumlah yang tepat, pertimbangkan untuk menambahkan logika idempotensi—misalnya, dengan menggunakan ekspresi kondisi yang memeriksa apakah spesifik telah diproses. `DownloadID`

## Desain GSI jarang
<a name="bp-gsi-aggregation-sparse-gsi"></a>

Untuk melakukan kueri hasil agregat secara efisien, buat indeks sekunder global dengan skema kunci berikut:
+ **Kunci partisi GSI:** `Month` (String)
+ **Kunci sortir GSI:** `DownloadCount` (Nomor)

GSI ini *jarang* karena hanya item agregasi bulanan yang berisi atribut. `Month` Catatan unduhan individual tidak memiliki atribut ini, sehingga secara otomatis dikecualikan dari indeks. Ini berarti GSI hanya berisi item agregasi yang telah dihitung sebelumnya—sebagian kecil dari total item dalam tabel.

GSI yang jarang memberikan dua manfaat utama:
+ **Biaya lebih rendah** — Karena hanya item agregasi yang direplikasi ke indeks, Anda mengkonsumsi kapasitas tulis dan penyimpanan yang jauh lebih sedikit dibandingkan dengan indeks yang mencakup setiap item dalam tabel.
+ **Kueri yang lebih cepat** — Indeks hanya berisi data yang perlu Anda kueri, sehingga pembacaan efisien dan mengembalikan hasil dengan latensi milidetik satu digit.

Untuk informasi selengkapnya tentang cara kerja indeks sparse, lihat. [Memanfaatkan indeks jarang](bp-indexes-general-sparse-indexes.md)

## Menanyakan GSI
<a name="bp-gsi-aggregation-querying"></a>

Dengan GSI yang jarang, Anda dapat menjawab beberapa jenis kueri secara efisien:

**Dapatkan lagu yang paling banyak diunduh untuk bulan tertentu:**

```
aws dynamodb query \
    --table-name "MusicLibrary" \
    --index-name "MonthDownloadsIndex" \
    --key-condition-expression "#m = :month" \
    --expression-attribute-names '{"#m": "Month"}' \
    --expression-attribute-values '{":month": {"S": "2018-01"}}' \
    --scan-index-forward false \
    --limit 1
```

Pengaturan `ScanIndexForward` untuk `false` mengurutkan hasil berdasarkan `DownloadCount` urutan menurun, dan hanya `Limit=1` mengembalikan lagu teratas.

**Dapatkan 10 lagu teratas untuk bulan tertentu:**

```
aws dynamodb query \
    --table-name "MusicLibrary" \
    --index-name "MonthDownloadsIndex" \
    --key-condition-expression "#m = :month" \
    --expression-attribute-names '{"#m": "Month"}' \
    --expression-attribute-values '{":month": {"S": "2018-01"}}' \
    --scan-index-forward false \
    --limit 10
```

**Dapatkan semua lagu diunduh dalam bulan tertentu** (diurutkan berdasarkan jumlah unduhan):

```
aws dynamodb query \
    --table-name "MusicLibrary" \
    --index-name "MonthDownloadsIndex" \
    --key-condition-expression "#m = :month" \
    --expression-attribute-names '{"#m": "Month"}' \
    --expression-attribute-values '{":month": {"S": "2018-01"}}' \
    --scan-index-forward false
```

## Pertimbangan-pertimbangan
<a name="bp-gsi-aggregation-considerations"></a>

Ingatlah hal berikut saat menerapkan pola ini:
+ **Konsistensi akhir - Nilai agregasi diperbarui secara asinkron melalui DynamoDB** Streams dan Lambda. Biasanya ada penundaan beberapa detik antara unduhan yang direkam dan agregasi yang diperbarui. Ini berarti GSI mencerminkan data mendekati waktu nyata, bukan data waktu nyata.
+ **Konkurensi Lambda** - Jika tabel Anda memiliki volume tulis yang tinggi, beberapa pemanggilan Lambda dapat mencoba memperbarui item agregasi yang sama secara bersamaan. `ADD`Operasi atom menangani ini dengan aman, tetapi Anda harus memantau metrik konkurensi dan pelambatan Lambda untuk memastikan fungsi Anda dapat mengikuti aliran.
+ **Kapasitas tulis GSI** - Karena GSI jarang hanya berisi item agregasi, ini membutuhkan kapasitas tulis yang jauh lebih sedikit daripada tabel dasar. Namun, Anda tetap harus menyediakan kapasitas yang cukup (atau menggunakan mode sesuai permintaan) untuk menangani tingkat pembaruan agregasi.
+ **Perkiraan hitungan** - Seperti disebutkan sebelumnya, percobaan ulang Lambda dapat menyebabkan jumlah menjadi sedikit terlalu banyak dihitung. Untuk kasus penggunaan yang memerlukan jumlah yang tepat, terapkan pemeriksaan idempotensi dalam fungsi Lambda.