Menengah7 menit baca

Strategi filtering DynamoDB

"Filtering" di DynamoDB berarti empat hal berbeda dengan kata yang sama. Tiga mempersempit data sebelum dibaca dan ditagih; satu — yang bernama Filter — mempersempitnya sesudah. Mengetahui mana yang mana adalah sebagian besar keterampilannya.

Bagaimana filtering bekerja di DynamoDB?

DynamoDB punya empat cara filter, dan hanya satu yang berjalan setelah Anda ditagih. memilih partisi, sort key mempersempit irisan, dan sparse index memfilter berdasarkan kehadiran atribut — ketiganya memotong biaya baca sebelum metering. FilterExpression berjalan setelah baca, jadi ia mengecilkan respons tetapi tidak pernah tagihan.

  • adalah filter termurah: ia memilih partisi, jadi Anda tidak pernah menyentuh sisa tabel.
  • memfilter di dalam partisi dengan begins_with, between, <, > — masih sebelum billing, masih murah.
  • memfilter berdasarkan ketiadaan: item hanya muncul di indeks jika ia punya atribut yang diindeks, jadi indeks adalah set yang difilter.
  • FilterExpression adalah jebakan: ia berjalan setelah DynamoDB mengukur baca, jadi ia memotong ukuran respons tetapi tidak pernah tagihan Anda.

Siapkan contohnya

Katalog produk. Satu tabel, partition key PK, sort key SK:

PK = "DEPT#kitchen"   SK = "PROD#00194"

Setiap produk juga membawa price, inStock (boolean), dan clearanceAt (timestamp unix, hanya hadir pada item yang ditandai clearance). Item dalam satu department berbagi partisi, diurutkan berdasarkan product id.

Kita ingin empat access pattern. Masing-masing memetakan ke strategi filtering berbeda — dan pilihan salah pada mana pun adalah Scan yang akan Anda bayar selamanya.

Filter dengan partition key

"Beri saya setiap produk di kitchen." Partition key menjawab ini langsung:

Query  PK = "DEPT#kitchen"

DynamoDB membaca tepat satu partisi. Tidak ada yang lain di tabel disentuh atau ditagih. Ini satu-satunya filter yang gratis dalam arti yang penting — perbedaan antara Query dan Scan.

Datang dari SQL, ini terasa terbalik: tidak ada WHERE department = 'kitchen' yang men-scan indeks, Anda sekadar menamai partisi. Jika Anda tidak bisa menaminya, itu masalah pemodelan, bukan masalah query.

Filter dengan sort key

"Beri saya produk kitchen dari PROD#00100 ke atas." Sort key mempersempit di dalam partisi, dan melakukannya sebelum baca diukur:

Query  PK = "DEPT#kitchen"  AND  SK between "PROD#00100" AND "PROD#00200"

Kondisi sort key dibatasi dengan sengaja: =, <, <=, >, >=, between, dan begins_with. Tanpa OR, tanpa predikat arbitrer.

Batasan itulah yang menjaga baca tetap tertarget — DynamoDB menelusuri irisan kontigu, bukan seluruh partisi.

Tuas di sini adalah bagaimana Anda meng-encode sort key. Jika pola akses Anda "berdasarkan rentang harga", sort key PROD#<id> tidak membantu — Anda perlu memanggang harga ke dalam key.

Itu keputusan strategi sort key, dibuat saat desain, bukan saat query.

Filter dengan sparse index

"Beri saya semua yang sedang clearance." Sebagian besar produk tidak, jadi Anda tidak ingin membaca katalog untuk menemukan sedikit yang ya.

Sparse index menyelesaikan ini lewat ketiadaan. hanya berisi item jika item itu punya kedua atribut key indeks.

Set flag konstan clearance = "CLEARANCE" sebagai partition key GSI — ditulis hanya pada item clearance — dengan clearanceAt sebagai sort key, dan indeks tidak menampung yang lain.

AWS menjelaskannya: global secondary index hanya berisi item yang punya atribut key indeks, jadi item yang kehilangan atribut key sekadar tidak dipropagasi (AWS — Take advantage of sparse indexes).

YaTidakTabel dasar semua produkPunya clearanceAt?Direplikasi ke ClearanceIndexTidak di indeksQuery indeks = hanya itemclearance

Sekarang query hanya membaca item clearance, ditagih hanya untuk mereka:

Query  ON ClearanceIndex   GSI_PK = "CLEARANCE"   (sorted by clearanceAt)

Filter terjadi saat Anda menulis data — dengan memilih apakah men-set clearanceAt sama sekali. Indeks adalah set yang difilter. Lihat GSI vs LSI untuk tipe indeks mana yang cocok.

Filter dengan FilterExpression

"Beri saya produk kitchen yang tersedia." inStock bukan atribut key, jadi Anda menjangkau FilterExpression:

Query  PK = "DEPT#kitchen"
Filter inStock = true

DynamoDB membaca setiap item di partisi kitchen, mengukur kapasitas untuk semuanya, dan lalu membuang yang tidak tersedia.

AWS menyatakan filter expression "applied after a Query finishes, but before the results are returned," dan "a Query consumes the same amount of read capacity, regardless of whether a filter expression is present" — Anda sudah membayar baca penuh (AWS — Filter expressions for Query).

Jadi jika kitchen punya 10.000 produk dan 12 tersedia, Anda membayar untuk membaca 10.000. Respons kecil; tagihan tidak. FilterExpression mengecilkan payload yang melintasi jaringan, bukan bacanya.

Ada tepi kedua yang lebih tajam: paginasi diukur sebelum filtering. Halaman adalah 1 MB item yang dibaca, bukan 1 MB yang cocok.

Filter bisa mengembalikan halaman kosong dengan LastEvaluatedKey ter-set — DynamoDB membaca satu megabyte penuh, tidak cocok apa pun, menyerahkan array kosong. Anda terus memaginasi, dan Anda membayar setiap halaman kosong.

Bangun expression — name, value, dan escaping reserved-word yang benar — dengan DynamoDB Expression Builder agar placeholder #inStock/:val benar pada percobaan pertama.

Builder di bawah di-preset ke Scan dengan FilterExpression — anti-pattern tepat di atas. Perhatikan filter berjalan pada seluruh tabel, bukan irisan key:

Bangun request Anda
Kode yang dihasilkan
new ScanCommand({
  "TableName": "AuditLog",
  "FilterExpression": "#filter0 = :filterValue0",
  "ExpressionAttributeNames": {
    "#filter0": "action"
  },
  "ExpressionAttributeValues": {
    ":filterValue0": {
      "S": "delete"
    }
  }
})

Bandingkan keempatnya

Kapan memfilterPotong biaya baca?Kekuatan predikatBiaya setup
Partition keySebelum bacaYa — satu partisiEquality sajaGratis (itulah key)
Sort keySebelum bacaYa — sebuah irisanRange / begins_withDesain sort key
Sparse indexSebelum bacaYa — hanya indeksKehadiran atributGSI ekstra + biaya tulis
FilterExpressionSetelah bacaTidakHampir kondisi apa punTidak ada

Baca tabel dari atas ke bawah: kekuatan predikat naik, kontrol biaya turun. FilterExpression bisa mengekspresikan apa pun justru karena berjalan pada item yang sudah dibaca — alasan yang sama mengapa ia tidak bisa menghemat uang Anda.

Lihat di DynoTable

Saat Anda menjalankan Query dengan filter, celah antara item yang dibaca dan item yang dikembalikan adalah seluruh ceritanya. DynoTable menampilkan item yang di-scan di samping item yang dikembalikan saat baca berfilter streaming — jadi filter yang diam-diam membaca seluruh partisi terlihat, bukan bersembunyi di tagihan bulanan Anda.

Untuk pertanyaan lintas-item sungguhan yang filter tidak bisa jawab — "harga rata-rata per department", "produk tersedia di-join ke ulasannya" — SQL Workbench DynoTable menjalankan GROUP BY, JOIN, dan agregat di sisi klien atas result set terbatas, alih-alih mengompilasi ke Scan seukuran tabel.

Jebakan dan langkah selanjutnya

  • Jangan pakai FilterExpression sebagai jalur akses utama. Jika pattern umum, model ke key atau sparse index. Filter untuk sedikit penyempitan terakhir, bukan sebagian besarnya.
  • Perhatikan halaman kosong. Query berfilter bisa memaginasi lama mengembalikan tidak ada. Hormati LastEvaluatedKey; jangan asumsikan halaman kosong berarti "selesai".
  • Sparse index tidak gratis. Ia menelan kapasitas tulis dan penyimpanan untuk setiap item yang mendarat di dalamnya — murah saat atribut jarang, kurang saat tidak.

Perkirakan biaya baca berfilter dengan kalkulator harga, dan coba DynoTable untuk menyaksikan consumed capacity terhadap baris yang dikembalikan di tabel Anda sendiri.

Diperbarui