Querying & Sorting
You add a filter to a Scan because it feels like SQL WHERE, then pay to read
every item in the table while the console shows twenty matching rows. That pattern
is a common DynamoDB cost surprise on production bills.
Reads in DynamoDB are keyed. Query walks one item collection in sort-key order;
Scan touches the whole table.
Filter expressions discard rows after capacity is charged. Pagination must carry
LastEvaluatedKey; sorting happens via the sort key of the index you chose, not an
arbitrary column in application memory.
What this section teaches you to do
- Choose
QueryvsScanfor a feature and defend the choice with partition scope. - Page through large result sets without dropping or duplicating items.
- Apply filters at the key condition when possible and know what a post-read filter still costs.
- Encode sort order in the sort key (zero-padding for numeric order, mutable values on a GSI key) and read it in either direction.
Reading order
- Query vs Scan: the billing decision every other read guide assumes you understand.
- Pagination:
LastEvaluatedKey, page loops, and whyLimitis not "rows returned." - Filtering strategies: key conditions vs filter expressions; narrow with the key first, and filter only what the keys can't.
- Why Scan is slow and expensive: table
growth vs partition growth; when a one-off
Scanis acceptable. - Parallel scans: segmented
Scanfor backfills and migrations; the throughput trade-off. - Sort key strategies: design the sort key so order is on disk, not in your app.
- Query descending order:
ScanIndexForwardand newest-first reads. - Mutable sort keys: why a key attribute can't be updated, and the GSI sort-key pattern that avoids delete+put.
- Zero-padding sort: fixed-width numeric
sort keys so
TICKET#00042sorts beforeTICKET#00100(unpadded,TICKET#100sorts beforeTICKET#42).
A Query on PK = TEAM#billing with SK begins_with TICKET# reads only that team's
tickets. A Scan with filter status = OPEN on a ten-million-item table still bills
the read of all ten million items.
At us-east-1 on-demand list price, a 4 KB read request unit costs $0.000000125: trivial per call, large at table scale. The pricing calculator prices your actual read rate and item size.
Parallel scans split a Scan across workers for jobs that must touch every live
item, like a backfill or a migration. They multiply the read rate, not the total:
the bill is the same as a sequential scan, it just arrives faster.
A wide parallel scan can starve live traffic. For a recurring dump to S3, use Export to S3 instead: it reads the point-in-time recovery backup, not the table.
Changing a base-table sort key means a delete and a put, in the table and in every
GSI the item appears in. The mutable-sort-key guide puts the volatile value on a GSI sort key instead, where a
plain UpdateItem moves it.
Zero-padding fixes lexicographic order when your sort key is a string carrying numeric IDs.
In DynoTable
The free query builder composes a full Query or
Scan request as a runnable program with its pagination loop (12 languages and
SDKs) or as a PartiQL statement.
In the app, the visual query builder lets you pick an index, and its run button reads Query or Scan depending on the key condition, so you know which read you're about to pay for.
Download DynoTable and execute these reads against a live table. The
query cost status bar gives a pre-run hint (~N items · ~R RCU when the plan is
known) on Workbench and PartiQL tabs so surprise bills surface before you run.