A Query reads only the items that share one partition key value, while a Scan reads every item in a table or index. Query is cheaper and faster, and Scan is a last resort on large tables.
Query needs the partition key value of the table or index, and it can narrow results with a sort key condition.
Query returns items in sort key order.
Scan's cost and time grow with the table, not with the result.
Both accept a filter expression that returns a subset. It runs after the read, so filtered-out items still cost read capacity.
Avoid Scan in production on large tables. Keep it for exports and small tables, and add an index for another access pattern.
# Query example
response = table.query(
KeyConditionExpression=Key('user_id').eq('123')
)
# Scan example
response = table.scan(
FilterExpression=Attr('age').gt(21)
)
Rewriting in plainer words…
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.