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
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 hampir real time, atau platform e-commerce mungkin perlu menampilkan produk yang sedang tren berdasarkan kategori.
Karena DynamoDB tidak secara native mendukung operasi agregasi seperti SUM atau COUNT di seluruh item, menghitung nilai-nilai ini pada waktu baca akan membutuhkan pemindaian item dalam jumlah besar—yang mungkin lambat dan mahal. Sebagai gantinya, Anda dapat melakukan pra- perhitungan agregasi saat data berubah dan menyimpan hasilnya sebagai item biasa di tabel Anda. Pola ini disebut agregasi terwujud.
Topik
Contoh skenario dan pola akses
Pertimbangkan aplikasi perpustakaan musik dengan persyaratan berikut:
Aplikasi merekam unduhan lagu individual dengan 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 dalam 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
Ada beberapa pendekatan untuk komputasi agregasi. Tabel berikut membandingkan alternatif umum dan menjelaskan mengapa agregasi terwujud di DynamoDB seringkali paling cocok untuk jenis kasus penggunaan ini.
| Pendekatan | Pengorbanan | Kapan harus digunakan |
|---|---|---|
| Pindai dan hitung saat membaca | 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 masalah. |
| 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 | Pasangkan logika agregasi ke jalur tulis. Jika aplikasi gagal setelah merekam unduhan tetapi sebelum memperbarui hitungan, agregasi menjadi tidak konsisten. | Ketika Anda membutuhkan agregasi sinkron, sangat konsisten dan dapat mentolerir latensi penulisan tambahan. |
| Agregasi terwujud dengan Streams dan Lambda | Memisahkan agregasi dari jalur tulis. Agregasi akhirnya konsisten (biasanya beberapa detik di belakang). Menambahkan biaya pemanggilan Lambda. | Ketika Anda membutuhkan agregasi hampir real-time dengan latensi baca rendah dan dapat mentolerir konsistensi akhirnya. Ini adalah pendekatan yang dijelaskan di halaman ini. |
Pendekatan agregasi yang 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
Desain ini menggunakan satu tabel 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 pengurutan adalah
DownloadID(pengidentifikasi unik untuk setiap unduhan).Item agregasi bulanan — Pre-computed jumlah unduhan per lagu per bulan. Kunci pengurutan adalah bulan dalam
YYYY-MMformat (misalnya,2018-01). Item-item ini juga berisiDownloadCountatribut dengan total berjalan.
Hanya item agregasi bulanan yang berisi Month atribut. Perbedaan ini penting untuk desain GSI jarang yang dijelaskan kemudian.
Diagram berikut menunjukkan tata letak tabel dengan kedua jenis item:
| Jenis barang | Kunci partisi (SongID) | Urutkan kunci | Atribut tambahan |
|---|---|---|---|
| Unduh rekaman | song1 |
download-abc123 |
UserID, Timestamp |
| Agregasi bulanan | song1 |
2018-01 |
Month=2018-01,
DownloadCount=1,746,992 |
Pipa agregasi dengan Streams dan AWS Lambda
Pipa agregasi bekerja sebagai berikut:
Saat lagu diunduh, aplikasi menulis item baru ke tabel dengan
Partition-Key=songIDdanSort-Key=DownloadID.DynamoDB Streams menangkap penulisan ini sebagai catatan aliran.
Fungsi Lambda, yang dilampirkan ke aliran, memproses catatan baru. Ini mengidentifikasi
songIDdan bulan saat ini, kemudian memperbarui item agregasi bulanan yang sesuai dengan menambah atribut.DownloadCountItem agregasi yang diperbarui kemudian tersedia untuk kueri melalui GSI yang jarang.
Fungsi Lambda menggunakan UpdateItem panggilan dengan ADD ekspresi untuk meningkatkan jumlah unduhan secara atomik. Ini menghindari kondisi balapan baca-modifikasi-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, rekaman aliran dapat dicoba lagi. Karena ADD operasi menambah jumlah setiap kali dijalankan, percobaan ulang akan menambah jumlah 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 DownloadID telah diproses.
Desain GSI jarang
Untuk menanyakan hasil agregat secara efisien, buat indeks sekunder global dengan skema kunci berikut:
Kunci partisi GSI:
Month(String)Kunci pengurutan 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 pra—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 menggunakan kapasitas penulisan dan penyimpanan jauh lebih sedikit dibandingkan dengan indeks yang menyertakan setiap item dalam tabel.
Kueri yang lebih cepat — Indeks hanya berisi data yang Anda butuhkan untuk kueri, sehingga pembacaan efisien dan mengembalikan hasil dengan latensi milidetik satu digit.
Untuk informasi selengkapnya tentang cara kerja indeks sparse, lihat. Memanfaatkan indeks jarang
Menanyakan GSI
Dengan GSI yang jarang, Anda dapat secara efisien menjawab beberapa jenis pertanyaan:
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 false untuk mengurutkan DownloadCount hasil menurut 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 yang 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
Ingatlah hal-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 hampir real-time, bukan data real-time.
Konkurensi Lambda — Jika tabel Anda memiliki volume tulis yang tinggi, beberapa pemanggilan Lambda dapat mencoba memperbarui item agregasi yang sama secara bersamaan.
ADDOperasi atom menangani ini dengan aman, tetapi Anda harus memantau konkurensi Lambda dan metrik pelambatan untuk memastikan fungsi Anda dapat mengikuti aliran.Kapasitas tulis GSI — Karena GSI jarang hanya berisi item agregasi, ia membutuhkan kapasitas tulis yang jauh lebih sedikit daripada tabel dasar. Namun, Anda masih harus menyediakan kapasitas yang cukup (atau menggunakan mode on-demand) untuk menangani tingkat pembaruan agregasi.
Perkiraan jumlah — Seperti disebutkan sebelumnya, percobaan ulang Lambda dapat menyebabkan jumlah sedikit dihitung berlebihan. Untuk kasus penggunaan yang memerlukan jumlah yang tepat, terapkan pemeriksaan idempotensi dalam fungsi Lambda.