Before we start
This course is independent of Google. Google has not endorsed it. BigQuery changes often, so when a limit or a price matters to you, check Google's current documentation. The figures in this lesson were current in October 2026.
You already write SQL against a database such as PostgreSQL or SQL Server. You'll find BigQuery accepts much of that SQL. What surprises people is how BigQuery runs your queries and how it bills for them. Get that model right in this first lesson and the cost-control advice in later lessons will make sense.
What "serverless data warehouse" means
- Data warehouse: a system built for analysis (scanning millions of rows to total, group and compare). Your PostgreSQL app database is built for a different job: lots of small, fast reads and writes of single records.
- Serverless: you never create, size or patch a server. There is no instance to start and no "how many CPUs?" question. You write a query, and Google runs it on as many machines as it needs. When the query finishes, those machines go back to the pool.
Here's a comparison that helps. PostgreSQL is a car you own: it costs money while it sits in the drive, and it can only go as fast as its engine. BigQuery is a taxi fleet. You pay for the journeys you take, and a big job can use a lot of cars at once.
Storage and compute live apart
Google's own docs describe the separation of storage and compute as a key feature of BigQuery's architecture. Your tables sit in Google's distributed storage, and queries run on a separate pool of compute. Each side grows on its own, so you can store a lot and query a little, or the other way round.
That split shows up on the bill as two separate meters:
| Meter | What you pay for | Rough mental model |
|---|---|---|
| Storage | Data kept in your tables, per GiB per month | Rent on a storage unit |
| Compute (on-demand) | Bytes your queries read, per TiB | A fee each time you open the unit and carry boxes out |
On the on-demand model, queries cost $6.25 per TiB processed (US pricing), and the first 1 TiB each month is free. Storage has its own free allowance: the first 10 GiB each month.
Worked example: suppose a query reads 50 GiB.
50 GiB / 1024 = ~0.049 TiB
0.049 TiB x $6.25 = ~$0.31 (or $0, if it fits in your free 1 TiB this month)
The query took the same compute whether the table holds 5 GiB or 5 TiB of data you didn't touch. You pay for what the query reads, not for how big the table is.
Why it feels different: columns, not rows
PostgreSQL and SQL Server store each row together on disk. BigQuery stores table data in columnar format: each column is kept separately.
Row store (PostgreSQL): Column store (BigQuery):
[TX, F, 1990, Mary, 120] state: [TX, TX, CA, ...]
[TX, F, 1990, Anna, 85 ] gender: [F, F, M, ...]
[CA, M, 1991, John, 200] year: [1990, 1990, 1991, ...]
name: [Mary, Anna, John, ...]
number: [120, 85, 200, ...]
This has three consequences you'll feel straight away:
- Naming fewer columns reads fewer bytes. If your query uses
nameandnumber, BigQuery reads only those two columns. The other three stay on disk and you aren't billed for them. SELECT *is expensive. It reads every column, so it's billed for every column.LIMITdoesn't cut the bill. Google's cost guide says that for non-clustered tables,LIMITdoesn't change how much data is read. You get 10 rows back but pay for the full scan of each column you named.
Gotcha from the field: In PostgreSQL,
SELECT * FROM big_table LIMIT 10is a cheap way to peek at a table. In BigQuery it can be the most expensive query you run all day. Use the table's Preview tab instead (Lesson 2 shows you where it is).
You also won't find indexes to create. BigQuery gets its speed by reading a few columns across lots of machines in parallel.
Walkthrough: your first query and its bytes
Open the BigQuery console at console.cloud.google.com/bigquery. Lesson 2 covers projects and the free sandbox in detail. For now, an open query editor is enough. Paste this:
-- Top 5 girls' names in Texas, all years combined.
-- The table is a free public dataset of US baby names (from 1910 on).
SELECT
name, -- column 1 we read
SUM(number) AS total_babies -- column 2 we read
FROM `bigquery-public-data.usa_names.usa_1910_current` -- project.dataset.table, in backticks
WHERE state = 'TX' -- column 3 we read (filters still read the column)
AND gender = 'F' -- column 4 we read
GROUP BY name
ORDER BY total_babies DESC
LIMIT 5; -- trims the output, NOT the bytes read
Before you click Run, look at the top right of the editor. The validator shows a message like "This query will process X MB when run." That's an estimate, and Google documents it as an upper bound. The real figure can come in lower.
Click Run. In the results panel, open the Job information tab. You'll find:
- Bytes processed: how much data the query actually read.
- Bytes billed: what on-demand pricing charges you for. It can differ slightly from bytes processed because of rounding rules.
Check your answer. The results show five names with large totals. Mary has long been near the top for Texas girls.
Check your cost. Bytes processed should be in megabytes, nowhere near your free 1 TiB.
Try it: prove the column rule yourself
Run the query again with the gender filter removed, and compare the two bytes-processed figures. The second one is smaller because one fewer column is read. Now put gender back and change LIMIT 5 to LIMIT 1. The bytes don't move.
Note: if you run the exact same query twice, the second run may come back instantly with 0 bytes billed. That's BigQuery's result cache. Later lessons cover it, so for now change the query a little between runs when you're comparing.
Key takeaways
- BigQuery is a serverless warehouse. There are no servers to size, and Google provides compute for each query.
- Storage and compute are separate, so you get two meters: storage per GiB per month, and queries per TiB read ($6.25/TiB on-demand, first 1 TiB per month free).
- Data is stored by column. Cost depends on which columns you touch, not how many rows you return.
SELECT *reads everything. On non-clustered tables,LIMITdoesn't reduce the bytes read.- Before you run a query, read the validator's estimate. Afterwards, confirm the real figure under Job information → Bytes processed.