Reduce BigQuery scans without changing the answer
On this page
This check is due for a source refresh. Confirm the current documentation before you rely on provider-specific details.
Unnecessary scans increase on-demand BigQuery charges per TiB processed, so review partition filters and dry-run bytes before running your SELECT. Only change filters that preserve the required answer. Treat estimates for clustered tables as uncertain, not as final costs.
What you need first
- Tool
- BigQuery is Google Cloud's service for querying data. Start with the exact read-only SELECT and its referenced table definitions. A dry run estimates bytes processed before normal query execution.
- Access
- Ask an authorized BigQuery colleague to provide table definitions and dry-run estimates for the exact SELECT and intended project and datasets.
- If you do not use that tool
- Send a BigQuery engineer the SELECT, project, datasets and required data range. Request partitioning details, clustered columns in order, and dry-run bytes for the original and proposed SELECTs. Ask the query owner to confirm that both preserve the required answer.
Why this is worth a look
Skipping a qualifying partition filter can make BigQuery scan data the answer does not need. Partition pruning skips those partitions and excludes them from scanned bytes. Clustering can also skip storage blocks, but the blocks scanned and final cost are not known before execution.
Run this check
CHECKLISTWork through these steps with an authorized BigQuery colleague using BigQuery dry runs, not normal query execution. Scope: one SELECT and its referenced tables. Record logical (uncompressed) bytes for the query's required data range, not a monthly total.
1. Record the exact SELECT, project, datasets, referenced tables and required data range. Confirm that the query uses on-demand pricing, charged per TiB processed, rather than capacity pricing for compute resources called slots.
2. Read each table's partitioning type and column. Record clustered columns in their defined order, which affects which filters benefit from clustering. Do not change table definitions.
3. Review only filters that preserve the required answer. To enable partition pruning, use a constant filter expression and isolate the partitioning column on one side of a comparison. For time ranges, use >= and < with the required boundaries. Do not rely on functions over an integer-range partitioning column to prune partitions.
4. Check ingestion-time boundaries separately. _PARTITIONTIME is UTC ingestion time truncated to the partition boundary; daily partitions also expose _PARTITIONDATE. Ask the query owner whether filtering ingestion time would exclude any required rows.
5. Request dry runs of the original and proposed SELECTs. Record each SQL statement, its estimated bytes and its required range. Compare bytes to assess pruning. Mark clustered-table estimates as uncertain. Return any unresolved answer-equivalence question to the query owner before normal execution.How to confirm it
- 01
Confirm this is a scan-cost decision
Ask the workload owner whether this SELECT uses on-demand pricing. Continue for charges per TiB (tebibyte) processed, not charges for compute capacity called slots.
- 02
Agree on the required answer
Ask the query owner to state which rows and date range must remain. Do not add a narrower filter just to reduce estimated bytes.
- 03
Compare read-only estimates
Use the checklist with your BigQuery colleague to review table layout and compare dry-run bytes. Keep the exact SQL beside each estimate so the decision applies to the statement that will run.
- 04
Resolve uncertainty before execution
Wait for the query owner to confirm that any rewrite preserves the answer. If approval needs an exact pre-execution cost for a clustered-table query, do not approve it on the dry-run estimate alone.
Before making changes
Treat dry-run bytes as an estimate, not a bill or proof of identical results. This assumes a read-only, on-demand SELECT and unchanged tables between estimation and execution. Clustered-table costs remain uncertain until execution. Billing has a minimum of 10 MiB (mebibytes) per referenced table and 10 MiB per query, so very small scans can cost more than their estimated bytes suggest.