Skip to content
Finitizer

UPDATE, DELETE and MERGE bill the table they change

On demand, a one-row UPDATE can bill a whole table.

Filter on the partition column so only the partitions it touches are billed.

Check one of your own queries for this

Paste a query and the calculator estimates what it scans and flags the patterns it can detect statically. It runs in your browser.

What it is

On demand, BigQuery bills DML for the whole table it changes, plus what it reads from other tables. On a partitioned table, it bills the partitions it touches, not the whole table.

Why it costs money

  • The rows changed do not matter. The size of what they sit in does.
  • A MERGE bills the same, unless every clause only inserts. INSERT bills the bytes read, and TRUNCATE TABLE is free. So is a DELETE filtered on the partition column alone: it drops whole partitions.
  • On a schedule it repeats: an hourly MERGE into a 1 TiB table bills over 730 TiB a month.

Worked example

Expensive
UPDATE `analytics.events`
SET country = 'CA'
WHERE user_id = 42
Cheaper
UPDATE `analytics.events`
SET country = 'CA'
WHERE event_date = '2026-11-01'
  AND user_id = 42
The arithmetic. On a 1 TiB table with 1,000 daily partitions, the first bills the whole 1 TiB ($6.25) to change one row. The second bills about 1 GiB, under a cent.

How to fix it

  1. 1Filter on the partition column in every UPDATE, DELETE and MERGE.
  2. 2Batch changes into one MERGE rather than many small statements.
  3. 3To remove old data, DELETE on the partition column alone: it bills nothing.
  4. 4For a full reload, TRUNCATE TABLE is free, or replace the partition with a load job.
The calculator detects this one. Paste your query into the BigQuery Query Cost Calculator 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.

See how Finitizer works