All BigQuery cost anti-patterns

What SELECT * actually costs in BigQuery

BigQuery bills the columns you read, not the rows you return, so SELECT * is the most expensive way to write any query.

What it is

BigQuery stores data column by column. A query is billed for the total logical size of the columns it touches — every row of those columns, regardless of how many rows come back. SELECT * touches all of them.

Why it costs money

  • Row count is irrelevant to the bill. A query returning 10 rows from a 4 TiB table can bill the full 4 TiB if it reads every column.
  • Wide tables make this worse in exact proportion to their width. A 300-column event table where you need 4 columns bills roughly 75× what it needs to.
  • The habit spreads: a view defined with SELECT * imposes the cost on every query that reads the view, even one selecting a single column from it.

Worked example

Expensive
SELECT * FROM `analytics.events` WHERE event_date = "2026-08-01"
Cheaper
SELECT user_id, event_name, event_timestamp
FROM `analytics.events`
WHERE event_date = "2026-08-01"
The arithmetic. On a 2 TiB, 180-column table where those three columns are ~18 GiB, the first query bills 2 TiB ($12.50 at $6.25/TiB) and the second bills 18 GiB ($0.11). Run hourly, that is the difference between $9,000 and $79 a month.

How to fix it

  1. 1Name the columns. It is the entire fix.
  2. 2When you genuinely need most columns, SELECT * EXCEPT(big_json_blob, raw_payload) excludes the expensive ones and still bills only what remains.
  3. 3To look at data rather than query it, use table preview or `bq head` — preview reads no billable bytes at all.
The analyzer detects this one. Paste your query into the BigQuery Query Cost Analyzer and it will point at the exact line.

Fixing one query is satisfying. Fixing the pattern is the win.

Finitizer finds every instance of this across your BigQuery job history, ranks them by what they actually cost, and keeps checking after you have fixed them.