DynamoDB GROUP BY: Cara Mengagregasi Tanpa Klausa GROUP BY
Tidak ada GROUP BY di DynamoDB. Tidak ada COUNT, SUM, atau AVG juga — tidak di
API native, dan tidak di PartiQL. DynamoDB adalah penyimpanan key-value / dokumen,
bukan engine analitik, jadi agregasi adalah sesuatu yang Anda bangun, bukan sesuatu
yang dilakukan query planner untuk Anda.
Bisakah Anda melakukan GROUP BY di DynamoDB?
Tidak. DynamoDB tidak punya GROUP BY, HAVING, atau fungsi agregat seperti COUNT,
SUM, dan AVG — tidak di API native maupun di PartiQL, yang SELECT-nya hanya
menerima WHERE dan ORDER BY. Anda mengagregasi dengan menghitung-sebelumnya total
saat data berubah (atomic counter atau rollup Streams + Lambda) atau dengan
mengelompokkan di sisi-aplikasi setelah membaca.
- Grammar PartiQL
SELECTDynamoDB adalahSELECT … FROM … [WHERE …] [ORDER BY …]— dan itulah seluruh daftarnya. Tidak adaGROUP BY, tidak adaHAVING, tidak ada fungsi agregat, tidak adaJOIN(referensi PartiQLSELECTAWS). - Karena DynamoDB "tidak secara native mendukung operasi agregasi seperti
SUMatauCOUNTlintas item," panduan AWS sendiri adalah untuk menghitung-sebelumnya agregat saat data berubah dan menyimpan hasilnya sebagai item biasa (AWS: agregasi termaterialisasi). - Alternatifnya — baca setiap item lalu agregasi di aplikasi Anda — bekerja, tetapi Anda membayar untuk membaca seluruh tabel pada setiap query.
- Untuk eksplorasi sekali-pakai, SQL Workbench DynoTable menjalankan
GROUP BY/COUNT/SUM/AVGlangsung terhadap tabel live — SQL yang ditolak endpoint PartiQL DynamoDB.
Mengapa agregasi sulit di DynamoDB
DynamoDB tidak punya engine agregasi waktu-scan. Query dan Scan mengembalikan item;
mereka tidak melipatnya. Scan membaca seluruh tabel 1 MB sekaligus, dan kapasitas
yang dikonsumsinya didasarkan pada item yang dibacanya, bukan baris yang Anda simpan —
sebuah FilterExpression diterapkan setelah scan tetapi sebelum hasil kembali,
jadi ia mempersempit set hasil tanpa menurunkan tagihan (referensi API Scan
AWS:
sebuah filter "tidak mengonsumsi read capacity unit tambahan"; kapasitas didasarkan
pada ukuran item yang di-scan, bukan yang dikembalikan). Tidak ada hook GROUP-BY untuk
menggantungkan sum atau count sejak awal.
PartiQL tidak mengubah ini. PartiQL adalah dialek kompatibel-SQL atas engine yang
sama, jadi ia mewarisi keterbatasan yang sama — ia permukaan sintaksis, bukan model
eksekusi baru. Grammar SELECT yang didokumentasikan
sederhananya tidak punya token GROUP BY. Untuk kesenjangan penuh antara PartiQL dan
SQL sungguhan, lihat PartiQL vs SQL.
Jadi pertanyaannya bukan "bagaimana saya menulis GROUP BY" — melainkan "di mana
agregat saya hidup, dan kapan ia dihitung?" Ada tiga jawaban.
Pola 1: agregasi saat tulis (atomic counter)
Jika Anda tahu grup di muka — hitung per status, total per pelanggan, unduhan per bulan — pelihara item counter dan perbaruinya pada setiap penulisan.
Gunakan update expression ADD agar inkremen atomik dan aman-konkurensi. ADD bekerja
pada angka dan set, dan ia menghindari race read-modify-write, jadi dua penulis yang
menginkremen counter yang sama tidak pernah saling menimpa
(AWS mencatat ADD atomik "menghindari race condition read-modify-write"):
UpdateItem
Key { pk: "STATS#orders", sk: "status#shipped" }
UpdateExpression "ADD orderCount :one"
ExpressionAttributeValues { ":one": 1 }
Ini adalah SELECT COUNT(*) … GROUP BY status Anda — kecuali hitungannya sudah duduk
di sana sebagai item, terbaca dalam GetItem satu-digit-milidetik. Trade-off-nya: Anda
harus tahu key pengelompokan pada waktu tulis, dan Anda menggandengkan pembaruan counter
ke jalur tulis. Jika aplikasi crash setelah penulisan tetapi sebelum pembaruan
counter, keduanya menyimpang dari sinkron — yang justru merupakan mode kegagalan yang
dipisahkan oleh pola berikutnya.
Pola 2: rollup DynamoDB Streams + Lambda
Ketika Anda tak ingin logika agregasi di jalur tulis — atau penulisan adalah PutItem
biasa yang sulit Anda bungkus — pindahkan ke hilir. Ini pola rekomendasi AWS sendiri,
agregasi termaterialisasi
(AWS: Menggunakan GSI untuk query agregasi termaterialisasi):
- Aplikasi menulis item mentah (sebuah order, sebuah unduhan, sebuah event). Tanpa logika agregasi.
- DynamoDB Streams menangkap penulisan sebagai record stream.
- Sebuah Lambda yang terpasang ke stream membaca item baru, menurunkan grup (status,
bulan, kategori…), dan
ADDke item agregat yang cocok denganUpdateItematomik — yang "menghindari race condition read-modify-write" saat banyak invokasi menyentuh counter yang sama. - Anda query agregat yang dihitung-sebelumnya — sering melalui GSI sparse yang
mengindeks hanya item rollup, jadi "10 teratas bulan ini" adalah satu
QuerydenganLimit 10.
Trik GSI sparse: hanya item agregat yang membawa atribut terindeks (mis. Month), jadi
baris event mentah dikecualikan dari indeks secara otomatis — "fraksi kecil dari total
item dalam tabel," yang menjaga indeks murah dan baca cepat.
Ini memisahkan agregasi dari jalur tulis dan menjaga penulisan tetap sederhana, dengan biaya eventual consistency — AWS mencatat "penundaan beberapa detik antara sebuah unduhan dicatat dan agregasi diperbarui." Untuk dashboard, leaderboard, dan counter tren itu tidak masalah.
Caveat retry yang sama berlaku: invokasi Lambda yang di-retry menjalankan ulang ADD,
jadi "sebuah retry akan menginkremen hitungan lebih dari sekali," meninggalkan nilai
aproksimatif. Untuk hitungan eksak, tambahkan idempotensi (mis. condition expression
yang berkunci pada id item sumber); jika tidak, margin kecil tak masalah untuk analitik
dan leaderboard.
Pola 3: pengelompokan sisi-aplikasi setelah Scan/Query
Opsi brute-force: baca item, kelompokkan di kode Anda.
groups = {}
for item in paginate(table.scan()): # atau query() untuk satu partisi
key = item["status"]
groups[key] = groups.get(key, 0) + 1Ini benar dan kadang merupakan keputusan yang tepat — tetapi jujurlah tentang biayanya.
Scan membaca setiap item dalam tabel, dan kapasitas bacanya sama terlepas dari
apakah Anda memfilter. Jadi pengelompokan sisi-aplikasi atas Scan penuh berarti Anda
membayar untuk membaca seluruh tabel pada setiap agregasi, dan latensi tumbuh seiring
tabel. AWS mendaftar "scan dan count saat baca" sebagai "hanya cocok untuk dataset
sangat kecil di mana latensi bukan masalah"
(AWS: Mengapa menghitung-sebelumnya agregasi).
Dipersempit ke satu partisi via Query (mis. hitung order untuk satu pelanggan),
pengelompokan sisi-aplikasi sangat masuk akal — Anda hanya membaca satu koleksi item.
Untuk kesenjangan biaya penuh antara keduanya, lihat
Query vs Scan. Untuk mengestimasi apa yang akan dibaca scan
agregasi tertentu sebelum Anda menjalankannya, ukur item representatif dengan
kalkulator ukuran item — kapasitas baca
dibulatkan ke atas per 4 KB,
jadi ukuran item menggerakkan tagihan.
Untuk SQL analitis yang benar-benar ad-hoc atas tabel DynamoDB — "GROUP BY status,
hitung mereka" sekali pakai yang Anda jalankan sekali — jawaban AWS adalah mengarahkan
engine terpisah ke sana: konektor Amazon Athena DynamoDB memungkinkan Anda query
tabel dengan SQL sungguhan (GROUP BY, agregat, bahkan JOIN ke sumber lain) via
konektor Lambda
(AWS: konektor Amazon Athena DynamoDB).
Ia men-scan tabel di balik layar, jadi ia alat reporting/BI, bukan jalur panas.
Pola mana yang saya pakai?
| Anda butuh… | Gunakan |
|---|---|
| Total grup yang dikenal di jalur baca panas | Pola 1 — atomic counter (ADD) |
| Agregat tanpa menyentuh jalur tulis | Pola 2 — rollup Streams + Lambda |
| Hitungan yang dipersempit ke satu partisi | Pola 3 — Query lalu kelompokkan di app |
| Total eksak, tanpa drift | Pola 1/2 dengan pengaman idempotensi |
GROUP BY sekali-pakai saat mengeksplorasi | DynoTable Workbench (di bawah) atau Athena |
| BI/reporting berulang dengan SQL | Konektor Athena DynamoDB |
Menjalankan GROUP BY langsung di SQL Workbench DynoTable
Pola di atas adalah cara Anda melayani agregat di produksi. Tetapi ketika Anda mengeksplorasi sebuah tabel — "berapa banyak order per status, sekarang juga?" — Anda tak ingin men-provision Lambda atau mendirikan Athena. Anda ingin mengetik query-nya.
Itulah gunanya SQL Workbench DynoTable. Ia menjalankan SQL sungguhan — GROUP BY,
COUNT, SUM, AVG, HAVING, bahkan JOIN — langsung terhadap tabel DynamoDB live
Anda, mengeksekusi agregasi di sisi-klien atas baris yang dibacanya. Ini SQL yang
ditolak endpoint PartiQL DynamoDB:
SELECT status, COUNT(*) AS orders, SUM(total) AS revenue
FROM "Orders"
GROUP BY status
HAVING SUM(total) > 1000
ORDER BY revenue DESCPembingkaian jujur: di balik layar DynoTable membaca item dengan cara yang diizinkan
API (Query di mana ia bisa, Scan di mana ia harus), memmaterialisasinya, dan
melakukan pengelompokan di Workbench — mekanika "baca lalu agregasi" yang sama dengan
Pola 3, hanya tanpa loop, dan dalam aturan pola-akses DynamoDB. Ia dibangun untuk
eksplorasi dan analisis ad-hoc, bukan untuk menggantikan rollup produksi di jalur
baca panas. Untuk itu, hitung-sebelumnya (Pola 1 / 2).
Untuk sisi JOIN dari wedge yang sama — DynoTable menjalankan join lintas-tabel yang
PartiQL juga tidak bisa — lihat DynamoDB JOIN. Membandingkan
klien GUI pada kemampuan ini persis? Lihat
perbandingan GUI DynamoDB.
FAQ
Apakah PartiQL DynamoDB mendukung GROUP BY?
Tidak. SELECT PartiQL DynamoDB mendukung WHERE dan ORDER BY saja — tidak ada
GROUP BY, HAVING, fungsi agregat, atau JOIN. Grammar-nya
didokumentasikan
sebagai SELECT … FROM … [WHERE …] [ORDER BY …].
Bisakah saya melakukan COUNT(*) atas seluruh tabel DynamoDB?
Tidak sebagai fungsi agregat — PartiQL tidak punya. API memberi Anda Select=COUNT pada
Scan/Query, yang mengembalikan hitungan item yang cocok tetapi tetap membaca (dan
menagih) setiap item yang disentuh scan (referensi API Scan
AWS:
kapasitas didasarkan pada item yang diperiksa, bukan yang dikembalikan). Untuk total
yang sering-dibaca, pelihara item counter (Pola 1).
Bisakah saya GROUP BY partition key?
Tidak di DynamoDB atau PartiQL. Jika "per partition key" adalah pola akses yang dikenal,
pelihara satu item agregat per key dengan ADD atomik (Pola 1), atau roll-up dengan
Streams + Lambda (Pola 2).
Bagaimana saya melakukan SUM atau AVG per grup?
SUM: pelihara total berjalan per grup dan ADD ke sana saat tulis. AVG: simpan baik
sum maupun count dan bagi saat baca — tidak ada average native. Untuk AVG eksploratif
sekali-pakai, jalankan di SQL Workbench DynoTable atau via konektor Athena DynamoDB.
Apakah ada workaround partiql group by?
Tidak ada yang di sisi-PartiQL. Entah hitung-sebelumnya agregat (counter/Streams) dan
SELECT item rollup, atau jalankan GROUP BY di engine yang punya — Workbench DynoTable
untuk ad-hoc, Athena untuk reporting berulang.
Ingin menjalankan GROUP BY terhadap tabel Anda sendiri tanpa menulis Lambda?
Coba DynoTable dan arahkan SQL Workbench ke tabel live.