← GCP Data Engineering

GCP Data Engineering · Chapter 03

Building a Data Warehouse in BigQuery

Cloud Storage and BigQuery are the two services you will use in almost every later chapter. This chapter builds a small warehouse layer by layer, and spends real time on the hardest part: modelling.

0 of – checks answered

01

Cloud Storage and BigQuery

Two fully managed services with no infrastructure to size. Look at what each one is, where the data lives, and what BigQuery is not.

Object storage for any file, any size

A fully managed service: no pre-sizing, no nodes, no bandwidth planning. Data engineers use it for database dumps, exports of historical data, model files and as the staging area before a warehouse load.

Model
Objects inside buckets
Bucket names
Globally unique
Typical role
Lake and staging layer
Limit to know
Single objects have a maximum size (a quota)

02

A warehouse, layer by layer

Data does not jump from source to dashboard. It passes through layers, and each layer has one job. Step through the book's bike-sharing pipeline.

The application database

In the book’s scenario a Cloud SQL (MySQL) database holds the stations table. In real life you extract from a replica, so the production database is not disturbed.

Example
MySQL on Cloud SQL
Job here
Be extracted from, not queried heavily

Notice the naming: raw_, dwh_ and dm_ prefixes make a dataset's role obvious. Datasets should also be named for business meaning, such as customer loans or website logs, not technical purposes such as layer 1.

03

Loading data safely

How you write into a table depends on whether the data is an event or a snapshot. Get this wrong and you get duplicates or lost rows.

Event or snapshot?

  1. 01 A customer taps a bike out of a dock at 08:03.

  2. 02 A docking station has a name, a region and a capacity.

  3. 03 A sensor reports 21.4 °C at 12:00:05.

Pick the write mode

  1. 01 Each day new bike trips arrive. A trip never changes once it has happened.

  2. 02 A stations file arrives daily as a full copy. Stations can be added, changed or removed, and you only need the current picture.

  3. 03 A one-off load must never overwrite a table that already has data.

04

Views or tables?

Both can serve a data mart. The right choice depends on data size and how often the result is used.

ViewTable (physicalised)
Extra storage None, only the SQL is savedStores a copy of the result
Freshness Always currentAs fresh as its last refresh
Cost of each read Re-runs the query every timeReads stored rows
Best when Source is small or the query is lightHeavy joins or aggregations reused many times
  1. 01 A small stations table, and a manager wants an always-fresh top-two-regions answer without storing anything extra.

  2. 02 1,000 dashboards each use a view that joins and aggregates five multi-petabyte tables.

  3. 03 You want zero extra storage and results that update the moment the source table does.

05

Data modelling

A data model represents the business in tables people can understand without asking you. Good models balance four things that pull against each other: real-world fit, consistency, query speed and storage.

Normalised vs denormalised: try it

A gender label stored as text on every person row is denormalised. Storing a small id and looking the label up in a reference table is normalised. Flip between them and see what each buys you.

Gender column stores
Rename "Woman" to "Female"
Reading the label
Risk

Storage is cheap in BigQuery and joins are far less scary than in the Hadoop era, so consistency and clarity usually win. But a model with no thought at all leaves you with duplicated data, conflicting numbers and users who no longer trust the warehouse.

Inmon or Kimball?

InmonKimball
Direction Top-down: central warehouse first, then martsBottom-up: start from user questions
Shape Highly normalisedFact and dimension tables (star schema)
Strength Consistency, single source of truthSpeed to value, ease of use, query performance
Weakness Slow to change and to buildSome inconsistency and duplication
  1. 01 Finance needs statements that cannot contain mistakes, from sources that rarely change, and accuracy matters more than build speed.

  2. 02 New sources and columns appear every week and the business wants answers quickly, even if some inefficiency remains.

  3. 03 You are building one enterprise-wide source of truth first, with every data mart obeying its rules.

The book's answer to "which is best for BigQuery" is both, depending on the use case. Whichever you pick, the whole organisation commits to it for a long time, so experienced modellers usually decide.

Facts and dimensions

A fact table holds measurements at a fixed granularity, such as trips per station per day. A dimension table holds the attributes that describe an entity, such as a station's name and region. In a star schema a dimension has no parent tables, so it is denormalised.

  1. 01 Total trips and total trip seconds per station per day.

  2. 02 Each station’s name, region and capacity.

  3. 03 A customer’s name, segment and signup date.

BigQuery also supports nested and repeated columns: store each region's stations inside the region row. You keep denormalised convenience and avoid repeating region fields, though SQL users new to nested data may find it awkward.

06

Hands-on: two scenarios

Do these in order. Part A gets you comfortable; part B builds the warehouse. Your ticks are saved in this browser.

Part A: get comfortable

  1. Open each service once in the console so its API is enabled for your project.

  2. Find Explorer, the query editor and the job and query history panels.

    
    						SELECT "hello world";
    					
  3. Use Create table, source Upload, and let BigQuery auto-detect the schema for a headed CSV. Then delete both when done.

  4. Add the project bigquery-public-data by name, open baseball.schedules, and read its size under Details before querying. Costs scale with bytes scanned.

    
    						SELECT * FROM `bigquery-public-data.baseball.schedules` LIMIT 1000;
    					
  5. A project-name prefix keeps it unique. Use the same location you will use for your datasets.

  6. Clone the book’s GitHub repository in Cloud Shell and copy the chapter 3 dataset into the bucket. The book uses gsutil; Google now recommends gcloud storage for the same job.

    
    						gcloud storage cp -r Data-Engineering-with-Google-Cloud-Platform/* gs://YOUR_BUCKET/from-git/
    					

Part B: build the bike-sharing warehouse

  1. This costs money by the hour. Use the smallest tier, set your own strong root password, and delete the instance as soon as you have exported the table.

  2. Give the Cloud SQL service account permission to write objects to the bucket first (an IAM role; Chapter 9 explains why).

  3. The export has no header row, so do not auto-detect. Type the schema yourself.

    
    						station_id:STRING,name:STRING,region_id:STRING,capacity:INTEGER
    					
  4. Top two regions by total station capacity, then save the result as CSV.

    
    						SELECT region_id, SUM(capacity) AS total_capacity
    FROM `PROJECT.raw_bikesharing.stations`
    WHERE region_id != ''
    GROUP BY region_id ORDER BY total_capacity DESC LIMIT 2;
    					
  5. Loop over a list of dataset names (raw, warehouse, marts) and create any that do not exist. Doing it in code is what makes it repeatable.

  6. Then prove there are two dates and no duplicate trip IDs.

    
    						SELECT DISTINCT DATE(start_date) FROM `PROJECT.raw_bikesharing.trips`;
    SELECT trip_id, COUNT(*) c FROM `PROJECT.raw_bikesharing.trips` GROUP BY trip_id HAVING c > 1;
    					
  7. Write the result of a SELECT on the public table into a table in your raw dataset.

  8. Group by station_id and confirm nothing appears twice.

  9. A daily fact table joined to a stations dimension. Run the fact build once per date.

  10. Daily trips, daily average duration, top five start stations by duration, and the three regions with the shortest total duration.

  11. Delete the Cloud SQL instance and any datasets and buckets you no longer need.

    
    						gcloud sql instances delete mysql-instance-source
    					

For the final self-check, add a question the model cannot yet answer (for example, top three regions by female riders on the latest date) and decide which fact and dimension tables you need. There is no single correct model.

07

Key terms

Bucket / object
A Cloud Storage container with a globally unique name, and the files inside it.
Dataset
A named group of BigQuery tables and views.
Colossus
Google’s distributed file system that holds BigQuery storage.
Staging layer
Files landed in Cloud Storage before loading.
Raw / warehouse / mart
The three dataset layers: as-loaded, modelled, and per-audience.
Event vs snapshot
Something that happened (append-only) vs something that exists (can change).
Write disposition
A load setting: append, truncate or write-if-empty.
Fact table
Measurements at a defined granularity.
Dimension table
Attributes describing an entity that supports facts.
Star schema
A fact table surrounded by denormalised dimensions.
Normalised / denormalised
Split into related tables to avoid repetition, or kept together for ease of use.

08

Check yourself

Pick an answer to see the reasoning straight away.

Q1

Why stage database extracts as files in Cloud Storage before loading into BigQuery?

Q2

A load from a bucket in one region fails against a dataset in another. What is the most likely rule you broke?

Q3

Why can BigQuery keep timestamps only in UTC, and what does that force on you?

Q4

Which best describes a BigQuery dataset?

Q5

In BigQuery, which trade-off does the book argue you can lean toward?

Q6

What does BigQuery’s nested and repeated data offer?

Study notes in my own words, following the structure of Adi Widjaja's Data Engineering with Google Cloud Platform (Packt, 2022). GCP changes quickly, so check each service's current documentation before relying on names, prices or console steps.