DynamoDB Scan di Python (boto3)
Sebuah scan di boto3 adalah dua keputusan: request-nya, dan bagaimana Anda memaginasinya. Cuplikan di bawah memakai paginator bawaan, yang bukan pembungkus buatan seseorang di sekitar loop Anda. Ia lima baris konfigurasi botocore, dan lima baris itulah yang menentukan apakah scan Anda benar dan berapa biayanya. (Apakah Anda memang seharusnya melakukan scan sama sekali adalah pertanyaan lain.)
Kode
import boto3
client = boto3.client("dynamodb")
paginator = client.get_paginator("scan")
items = []
for page in paginator.paginate(
TableName="Music",
FilterExpression="#filter0 >= :filterValue0",
ExpressionAttributeNames={"#filter0": "Year"},
ExpressionAttributeValues={":filterValue0": {"N": "2010"}},
):
items.extend(page["Items"])
print(f"Matched {len(items)} items")Penjelasan
- Paginator-nya adalah data, bukan kode. botocore menyertakan satu entri per operasi di
paginators-1.json; milikScanberbunyi{"input_token": "ExclusiveStartKey", "output_token": "LastEvaluatedKey", "limit_key": "Limit", "result_key": ["Items", "Count", "ScannedCount"], "non_aggregate_keys": ["ConsumedCapacity"]}. Semua hal di bawah ini turun dari key-key itu. PaginationConfig={"PageSize": n}menyetelLimit, karenaLimitadalahlimit_key-nya.Limitmembatasi item yang dibaca, tak pernah item yang dikembalikan, jadi dengan sebuahFilterExpressionsebuah halaman bisa kosong dan tetap berbiaya.MaxItemsmenghitung itemresult_keydan mengembalikanNextTokenyang bisa Anda lewatkan sebagaiStartingTokendi proses berikutnya. Ia tidak menghentikan request membaca melewati batas Anda.build_full_result()hanya mengagregasi fieldresult_key.Items,CountdanScannedCountdijumlahkan;ConsumedCapacityadalahnon_aggregate_key, jadi hasil gabungannya melaporkan kapasitas satu halaman seolah-olah itu kapasitas seluruh scan. Jumlahkan sendiri, per halaman, atau Anda akan melaporkannya terlalu rendah sebesar faktor jumlah halaman.FilterExpressionberjalan di sisi server setelah pembacaan, jadi Anda ditagih berdasarkanScannedCount, bukanCount.#filter0memberi alias padaYearkarena ia sebuah reserved word; tanpa alias itu request-nya gagal sebelum membaca apa pun.- Semua error datang sebagai
botocore.exceptions.ClientError. Cabangkan berdasarkane.response["Error"]["Code"]; kelas per-error hanya ada sebagai atribut yang dihasilkan pada client (client.exceptions.ProvisionedThroughputExceededException), tak pernah sebagai simbol yang bisa di-import. - Resource API adalah ergonomi yang satunya.
Table.scanmenerima tipe Python native, mengembalikan angka sebagaidecimal.Decimal, dan membangun filter denganAttr("Year").gte(2010)alih-alih map placeholder.
Berapa sebenarnya biaya satu halaman terfilter
60 item berukuran sekitar 2 KB masing-masing, Year = 2024 cocok pada dua di antaranya, PageSize=10, dijalankan terhadap DynamoDB Local:
page 1: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 2: Count=1 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 3: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 4: Count=1 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 5: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 6: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 7: Count=0 ScannedCount=0 CU=0.0 LastEvaluatedKey=no
total CU across pages: 15.0Empat dari enam halaman sungguhan tidak mengembalikan apa-apa, dengan harga penuh. Itulah bentuk bug yang keberadaan paginator-nya mencegahnya: loop buatan tangan yang berhenti saat Items kosong akan menyerah di halaman 1 dan melaporkan dua lagu yang cocok sebagai nol.
Halaman 7 adalah separuh lainnya. Halaman 6 mencapai Limit-nya tepat pada item terakhir di tabel, jadi DynamoDB tetap mengembalikan sebuah LastEvaluatedKey dan paginator-nya menghabiskan satu round trip lagi untuk mengetahui tak ada apa-apa lagi. Sebuah LastEvaluatedKey berarti "saya berhenti", bukan "masih ada lagi".
Memanggil build_full_result() pada scan yang sama melaporkan CapacityUnits: 2.5. Keenam halamannya memakan 15,0.
Paginasi tanpa menulis loop-nya
DynamoDB Query Builder merakit filter, map alias, dan loop paginasinya sebagai satu program yang siap dijalankan, jadi jebakan Limit-versus-Count di atas sudah tertangani sebelum Anda menempelkannya. Untuk memaginasi tabel sungguhan secara interaktif alih-alih dari sebuah skrip, unduh DynoTable.
Panduan terkait
- Query vs. Scan — kapan (jarang) sebuah
scanbisa dibenarkan. - Mengapa Scan DynamoDB saya lambat dan mahal? — model biayanya dan cara menghindarinya.
- Parallel scan — memecah tabel dengan
Segment/TotalSegments, satu paginator per segmen. - DynamoDB ProvisionedThroughputExceededException — apa yang dilakukan scan seluruh tabel terhadap kapasitas tabel provisioned.
Referensi
- Scan — Amazon DynamoDB API Reference
- scan — Boto3 DynamoDB.Client Reference
- Scan paginator — Boto3 DynamoDB Reference
- Scanning tables — Amazon DynamoDB Developer Guide
Terakhir diverifikasi 2026-07-28 terhadap dokumentasi resmi AWS yang ditautkan di atas.