Estimate what a query costs before you run it
This recipe tells you what already happened. The analyzer takes a query you have not run yet and estimates what it will scan, in your browser.
Which queries do we run over and over with the same result?
Find the repeated query shapes that are candidates for a materialized view or a scheduled table.
Reads metadata only, a fraction of a cent to run (10 MB minimum)Reviewed against Google’s docs, 23 Oct 2026
Permissions. Needs bigquery.jobs.listAll on the project for JOBS (BigQuery Resource Viewer has it); bigquery.jobs.create to run any query (BigQuery Job User has it).
Pick the region your data is in: every INFORMATION_SCHEMA view here is qualified by region.
-- Group queries by normalized shape: strip literals, collapse whitespace.
WITH normalized AS (
SELECT
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(UPPER(query), r"'[^']*'", "'?'"),
r'\b\d+\b', '?'
),
r'\s+', ' '
) AS query_shape,
total_bytes_billed,
total_slot_ms,
cache_hit
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND job_type = 'QUERY'
AND IFNULL(statement_type, '') != 'SCRIPT'
AND state = 'DONE'
AND error_result IS NULL
)
SELECT
COUNT(*) AS runs,
COUNTIF(cache_hit) AS cached_runs,
SUM(total_bytes_billed) AS total_bytes_billed,
ROUND(SUM(total_bytes_billed) / POW(1024, 4) * 6.25, 2) AS est_on_demand_usd,
ROUND(AVG(total_slot_ms) / 1000, 1) AS avg_slot_seconds,
SUBSTR(query_shape, 0, 300) AS shape_preview
FROM normalized
GROUP BY query_shape
HAVING runs >= 5
ORDER BY total_bytes_billed DESC
LIMIT 50;What it returns
- runs
- How many times this shape ran.
- cached_runs
- How many were free. A low ratio on a repeated query is the finding.
- shape_preview
- The query with literals replaced by ?, so runs with different dates group together.
How to read it
- High runs plus high total cost plus low cached_runs is the materialized-view shortlist. If the underlying data changes slowly, a scheduled table may be simpler and cheaper than an MV.
- The literal-stripping is crude on purpose; it will merge queries that differ only by a date filter, which is exactly what you want, and occasionally merge two genuinely different queries, which you will spot from the preview.
- Before building an MV, check whether the repeats come from a dashboard refreshing on a timer that nobody is looking at. That fix is free.
Run this once, or have it run every day.
Finitizer evaluates this class of question continuously against your live BigQuery estate, tracks how each number moves between runs, and turns findings into assigned tasks. Read-only and keyless.
See how Finitizer works