Querying

Know what a read costs

See what a read will cost before you run it, catch a wasteful filter while it runs, and total the capacity you consumed afterwards.

Dynomatic reports read cost at three points. Before you run, a strip under the Filters builder estimates what the next Run will read. While it runs, the progress label warns when a filter throws away most of what DynamoDB read. Afterwards, Command history totals the capacity your operations consumed. Every figure is in capacity units (RCU and WCU), never in dollars.

Before you run: the estimate strip

The strip sits under the query builder, below the Run button, and changes as you edit pills, pick an index or toggle a behavior on the mode pill. It is informational only and never blocks a Run.

What it says depends on the operation the next Run will send.

Next Run The strip reads
A Scan that stops before the end of the table Scan: about <n> RCU for this run of <n> items. The whole table is about <n> RCU.
A Scan with a filter Scan: at least <n> RCU for this run. The filter keeps it reading until it finds enough matches, up to <n> RCU for the whole table.
A Scan whose run reads the whole table Scan: about <n> RCU. This run reads the whole table, <n> items.
A Query with no filter Query: cost depends on how many items match. This run reads at most <n> items, up to about <n> RCU.
A Query with a filter Query: cost depends on how many items match, which is unknown until it runs.

A filter makes the Scan figure a floor rather than an estimate. DynamoDB applies a filter expression after it has read the items, and it charges for everything it read. A filtered run keeps requesting pages until it has returned enough matches, so it can read far more than one page. The same fact is why a filtered Query gets no figure at all. Nothing caps what it reads until it runs.

An unfiltered Query gets a ceiling rather than an estimate, because the run stops at its batch size whatever the key condition matches.

Which operation the strip assumes

The strip follows the same rules the builder uses to choose between Query and Scan:

  • The Run is a Query when a partition key condition is set on the selected index.
  • Force scan makes it a Scan.
  • A filter on one of the selected index’s own key attributes makes it a Scan, because DynamoDB rejects a Query that filters on its key.

Every Scan the builder sends reads the base table, so a Scan estimate always uses the table’s figures.

Where the numbers come from

The estimate averages the item count and size that DynamoDB reports for the table, or for the index a Query reads. DynamoDB refreshes those figures about every six hours. The strip’s Approximate label says so on hover: Averaged from the item counts and sizes DynamoDB reports, which it refreshes about every six hours. It is an approximation, not a bill.

From that average item size, the strip models the requests the Run will send:

  1. Each request asks for one page of items, up to the table’s page size, or the Limit set on the mode pill. DynamoDB stops any single request after 1 MB.
  2. DynamoDB charges each request for the bytes it reads, in 4 KB steps. A strongly consistent read costs one RCU per started 4 KB. An eventually consistent read costs half that.
  3. The run keeps requesting pages until it has returned the table’s stream batch size, or the Limit. A run therefore reads up to the end of the page that crosses that number.

Page size and stream batch size are set per table under Fetching & Editing in Table settings.

With Consistent read on, the strip prices a strongly consistent read and adds the · consistent 2× tag to its headline. Consistent read never applies on a GSI or under Force scan, so the strip prices those as eventually consistent.

Indexes that project only some attributes

A Query on an index with a KEYS_ONLY or INCLUDE projection adds a note under the headline.

  • On a GSI: Index <name> projects only some attributes. A GSI never fetches from the table, so results carry only those.
  • On an LSI: Index <name> projects only some attributes. Asking for any other one makes DynamoDB fetch each item from the table, which costs more than shown.

When there is no estimate

If DynamoDB has not reported an item count and size, there is nothing to average, and the strip says so instead: No estimate: DynamoDB has not reported an item count and size for this table. A Query on an index names the index instead of the table. A table or index that DynamoDB has not yet counted reports zero, so this is common on a new table.

While it runs: the wasteful filter warning

The progress label below the grid reports what the run has fetched, for example Fetched 4 items (1KB) in 12ms. When a filter is discarding most of what DynamoDB reads, an amber warning appears beside it:

Filter discarded 98% of scanned items

The warning appears once both of these are true for the run so far:

  • DynamoDB has scanned at least 1,000 items.
  • It scanned at least 10 items for every item it returned.

Below 1,000 scanned items the read is too small for the ratio to matter. At 10 to 1, an index keyed on the filtered attribute would read about a tenth of the items. The percentage rounds down, so it never says 100% while a row came back. The counts cover everything the tab has loaded, including Load more. The scanned count is the one DynamoDB reports with each page.

After the percentage, GSI candidates: lists the attribute paths the run’s filter expression reads, in the order they appear in it. These are the attributes an index could key on to do the filter’s work. On a Scan every pill compiles into the filter expression, key pills included, so key attributes can appear in the list. On a Query only the filter pills do.

The warning applies to Scans and Queries alike. It does not stop the run. Press Cancel loading to stop it.

After it runs: consumed capacity in Command history

Command history shows a capacity strip above its timeline. It totals the capacity consumed by exactly the operations the timeline lists, so every filter and pill you apply narrows the totals too.

The strip shows:

  • Read <n> RCU and Write <n> WCU, kept apart.
  • The number of operations it covers.
  • <n> without capacity units, when some of those operations recorded none. A vector search is one example, because DynamoDB charges it by request size.

Queries, Scans, item reads, schema queries, vector searches and PartiQL SELECT statements count as reads. Puts, updates, deletes, batch writes and other PartiQL statements count as writes.

Retained window or this session

A toggle picks what the totals cover.

  • Retained window covers every listed operation still in history.
  • This session covers the listed operations run since the app launched.

History keeps the last 500 entries, and the caption under the totals says the totals cover only what is still there. Once history is full, the Retained window caption adds Older runs may have been pruned. An operation pruned from history is in neither total.

Per table

Per table expands a breakdown sorted by read units, then write units. Each table row names the table and its workspace, with Read (RCU), Write (WCU) and Discarded by filters columns.

Under each table, one row per index splits its units:

  • Base table for units the table itself consumed.
  • GSI <name> and LSI <name> for each secondary index.
  • Not broken down for units the operation’s capacity report did not attribute to the table or an index.

Discarded by filters reads <pct>% of <n> scanned, summed over the table’s operations that reported a scanned count. It carries a Wasteful marker at the same thresholds as the live warning: at least 1,000 items scanned, and at least 10 scanned for every item returned.

Command history’s own cards use a looser test. An expanded Scan card warns when the operation scanned more than twice the items it returned.

Note: Command history requires the Pro plan. The estimate strip and the live warning do not.

Last updated on