BigQuery FinOps Query Pack

Which queries are scanning partitioned tables without a partition filter?

Find the queries that read every partition of a partitioned table — usually the single largest avoidable cost in a BigQuery estate.

Free to run — INFORMATION_SCHEMA scans no billable bytesChecked 4 Aug 2026

This recipe reads both region-scoped and dataset-scoped views, so it needs both.

-- Queries that touched a partitioned table but billed a suspiciously
-- large fraction of it. Heuristic: bytes billed within 20% of the table's
-- total logical size means little or no pruning happened.
WITH partitioned AS (
  SELECT DISTINCT table_schema, table_name
  FROM `my-project.my_dataset`.INFORMATION_SCHEMA.COLUMNS
  WHERE is_partitioning_column = 'YES'
),
sizes AS (
  SELECT table_schema, table_name, total_logical_bytes
  FROM `region-us`.INFORMATION_SCHEMA.TABLE_STORAGE
),
jobs AS (
  SELECT
    job_id, user_email, creation_time, total_bytes_billed,
    ref.dataset_id AS table_schema,
    ref.table_id   AS table_name,
    SUBSTR(REGEXP_REPLACE(query, r'\s+', ' '), 0, 300) AS query_preview
  FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT,
       UNNEST(referenced_tables) AS ref
  WHERE creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
    AND job_type = 'QUERY'
    AND state = 'DONE'
    AND error_result IS NULL
)
SELECT
  j.job_id, j.user_email, j.table_schema, j.table_name,
  j.total_bytes_billed,
  s.total_logical_bytes,
  ROUND(SAFE_DIVIDE(j.total_bytes_billed, s.total_logical_bytes), 3) AS fraction_of_table,
  j.query_preview
FROM jobs j
JOIN partitioned p USING (table_schema, table_name)
JOIN sizes s       USING (table_schema, table_name)
WHERE SAFE_DIVIDE(j.total_bytes_billed, s.total_logical_bytes) > 0.8
ORDER BY j.total_bytes_billed DESC
LIMIT 50;

What it returns

fraction_of_table
Bytes billed ÷ the table's total logical size. Near 1.0 means a full scan.
total_logical_bytes
The whole table, uncompressed — the denominator.

How to read it

  • The ratio is a heuristic, not proof. A query selecting every column of every partition scores ~1.0; so does one selecting one column across a table where that column is most of the bytes. Read the query preview before filing a ticket.
  • The fix is almost never "add a WHERE clause" in isolation — it is to set require_partition_filter on the table so the next person cannot make the same mistake.
  • Ratios above 1.0 happen and are not a bug: a self-join reads the table twice.

Take it further

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.