Getting started with Google BigQuery
Tags: bigquery, dataengineering, google
Published: 2022-10-14 18:39:58

---
title: Getting started with Google BigQuery
published: true
date: 2020-03-25 13:01:01 UTC
tags: bigquery,dataengineer,dataengineering,google
canonical_url: 
---

> This guide will tell you what is Google BigQuery, how can it leverage your data analyses and what cool features Google BigQuery offers that makes it a perfect solution for data warehousing.

Let’s start first talking what is data warehouse:

According to AWS: A **data warehouse** is a central repository of information that can be analyzed to make better informed decisions.

So basically, it is to extract all the data you can from different sources, and store them in a structured way in a central storage, where you will be able to do queries and generate insights and take decisions from data.

So, what is BigQuery?

![](https://cdn-images-1.medium.com/max/1024/1*Cw_xC_JBQ0DHGrjKkGpfxA.png)

BigQuery is Google’s fully managed, petabyte scale, low cost analytics data warehouse.

Fully managed: Plug and play, user doesn’t have to care about nothing in terms of infrastructure.

Petabyte scale: Quickly analyze gigabytes to petabytes of data.

Low cost analytics: Analyze up to 1 TB of data and store 10 GB of data for free each month. So, you can use it even without paying anything, only data storage, which is pretty cheap.

Google BigQuery has a lot of cool feature, but its more remarkable are:

1. NoOps.
2. Pay-as-you-go model.
3. Securely share insights.
4. Streaming ingestion captures and real time analyses.
5. Analyze up to 1 TB of data and store 10 GB of data for free each month.

One of the coolest things about Google BigQuery is its constant evolution and progress:

In 2016, on GCP Next, a query that represented a Petabyte took 245.7s (about 4 min).

In 2018, the same query over the same dataset took 1 min 53s. The difference was not in the performance but in the way data was analyzed (data was clustered and partitioned on the dataset).

In 2019, on Google Next, only 11s! were needed for the same query.

These facts are explained in this video:

{% youtube eOQ3YJKgvHE %}

The video also explains what is the difference between a traditional data warehousing and what BigQuery offers, I will try to summarize that here:

**Traditional approach for data warehousing:**

This approach is built using an event handler (e.g., Kafka)+ data warehouse (DW, e.g., Apache Hive) + transformation jobs, pipelines (e.g., Hadoop, Spark, Impala) + Any analytic tool for doing queries and create dashboards (e.g., Hive + Tableau). This architecture can process data in batches (historic data stored) and also in real-time (streaming data coming from sensors). However, there is crucial word that characterizes this approach: “on-prem”. What this means? That someone will have to install all these technologies in your data center or in machine and pay for all these resources even if they are not being used.

![](https://cdn-images-1.medium.com/max/1024/1*3zeKSVxa84gT8mpGcQb9YA.png)

**BigQuery modern data warehousing:**

![](https://cdn-images-1.medium.com/max/828/1*7P0ZSLaLhabCnJb-6M6D8g.png)

So, one of the coolest thing about BigQuery, is the separation of storage and computing, someone can scale up the storage infinitely and keep the same computing. Also someone can scale up computing without having to scale storage (All this is possible thanks to Google’s petabit network).

![](https://cdn-images-1.medium.com/max/1024/1*fIiaXq5dmMsQ6iOvaKLVkQ.png)
_BigQuery Architecture — Petabit Network_

It is also serverless. It is ready to use.

Also brings the possibility of doing real-time analyses (thanks to combine it with Google Dataflow), instead of the traditional approach where someone have to dump the data for a period of time to see what happened in that period (delayed results).

Centralized storage: Data is accessible to all tools which can leverage it (BI, ETL tools, Hadoop, ML tools, and so on). There is a bunch of connectors that read in parallel, without affecting one another.

Security: Detailed logs of what happened.

Sharing: Grant people access to your data (specially, using views of queries and analyses).

![](https://cdn-images-1.medium.com/max/842/1*A8WgSS772n7otW9uca9siA.png)

Predictive: BigQuery ML. What is going to happen tomorrow!

Models can be built based on the data in your data warehouse.

**BigQuery ML:**

There are several algorithms already implemented someone can use to make predictions.

![](https://cdn-images-1.medium.com/max/1024/1*QXjT3ben-N7q3g6vL-E9tg.png)

In the video, they mentioned that they took the Netflix dataset, for recommendations, they used a Matrix factorization algorithm, and obtained results more or less equivalent than the best results. Only because they were able to process the whole dataset, not because of the fanciness of the algorithm.

For neural networks (Alpha), Google ships the data to Cloud ML Engine, but all is transparent for the user.

**Auto ML Tables:**

Someone can point a BigQuery Table and generate a model without having a special degree in ML. Only setting what is the outcome that is wanted to be predict.

![](https://cdn-images-1.medium.com/max/880/1*Lbz0UxuOpdHlPRA8gFYIlg.png)

What is the difference with BigQuery ML?

AutoML is a black box, high accuracies can be obtained easily (in my experience with AutoML for images, overfitting is easy to obtain too, that’s why a good validation and test strategy must be taken into account).

BigQuery ML uses simpler models, easier to understand. Variables that produce the outcome can be also identified. However, it does require some knowledge in ML.

![](https://cdn-images-1.medium.com/max/1024/1*sde0IHEek-VltdhV0wLplg.png)

**Full list of features:**

- Serverless: Google does all resource provisioning.
- Real-time analytics: (Near real-time)
- Automatic high availability: Replicated storage in multiple locations
- Standard SQL: Reduces code rewrites (Columnar database)
- Federated query and logical data warehousing: Several external sources
- Storage and compute separation: Every column is stored in a separated file.
- Meant for immutable pretty large datasets. (Not a transactional DB)
- Automatic backup and easy restore: Seven-day history of changes.
- Geospatial data types and functions: SQL support for GeoJSON and WKT.  
More data is becoming to have location associate with it. Query directly from maps.
- Data transfer service
- Big data ecosystem integration: Dataproc and Dataflow connectors
- Petabyte scale
- Flexible pricing models
- Data governance and security: Security with fine-grained identity
- Geoexpansion: Geographic data control.
- Foundation for AI
- Foundation for BI
- Flexible data ingestion
- Programmatic interaction: REST API
- Rich monitoring and logging with Stackdriver

**Google Warehousing Architecture:**

![](https://cdn-images-1.medium.com/max/1013/1*aeXMOVnIf9sdUaXnAY4-wQ.png)

**Use cases:**

Before Google BigQuery had in its documentation like four main use cases, right now you can find a bunch of them [here](https://cloud.google.com/solutions). Let’s summarize a little bit two of them, which have the common steps involved in data engineering.

**1. Internet of things:**

![](https://cdn-images-1.medium.com/max/555/1*9Ayct4DRlOsa3Yw9D9mX0Q.png)

Google Cloud IoT is a complete set of tools to connect, process, store, and analyze data both at the edge and in the cloud.

Use cases:

1. Predictive maintenance
2. Real-time asset tracking
3. Logistics & supply chain management
4. Smart Cities & Buildings

More info can be found here:

Taken from:

[Overview of Internet of Things | Solutions | Google Cloud](https://cloud.google.com/solutions/iot-overview#pipeline_processing_tasks)

**2. Optimizing Large-Scale Ingestion of Analytics Events and Logs:**

In this architecture, data originates from two possible sources:

- Analytics events are published to a [Pub/Sub](https://cloud.google.com/pubsub) topic.
- Logs are collected using [Cloud Logging](https://cloud.google.com/logging).

Benefits:

1. Log integrity. No logs are lost due to streaming quota limits or sampling.
2. Cost reduction. Logs inserted in Cloud Storage using batch jobs.
3. Reserved query resources. Moving lower-priority logs to batch loading.

![](https://cdn-images-1.medium.com/max/771/1*mgW7ayopC4gUR42Q8GE7yA.png)

Streaming input: Immediate analysis, e.g., an event might indicate undesired client behavior or bad actors.

![](https://cdn-images-1.medium.com/max/737/1*mom50aEyeAZEroejt_KvcQ.png)

Batch process: Events that need to be tracked and analyzed on an hourly or daily basis.

![](https://cdn-images-1.medium.com/max/727/1*FIYJIXNPg8vKhdTY20UpQQ.png)

Streaming input: Critical logs.

![](https://cdn-images-1.medium.com/max/640/1*J1b9Ki_NiWEsg9tp9R2aaA.png)

Cold path: Don’t require near real-time analysis.

![](https://cdn-images-1.medium.com/max/640/1*DuxDhUCD9r0SfaUUNAJj4w.png)

**Taken from:**

[Architecture: Optimizing large-scale ingestion of analytics events and logs](https://cloud.google.com/solutions/architecture/optimized-large-scale-analytics-ingestion)

**Datasets:**

Commercial:

Commercial data providers are accelerating your time to insight by hosting their data offerings directly in BigQuery, Cloud Storage and Cloud Pub/Sub.

_Examples:_

- _AccuWeather: min/max temperatures, precipitation, and snowfall_
- _Dow Jones: historical News Snapshots_
- _HouseCanary: historical home price_
- _Xignite: financial market data_

Public:

A public dataset is any dataset that is stored in BigQuery and made available to the general public through the Google Cloud Public Dataset Program.

![](https://cdn-images-1.medium.com/max/1024/1*wrd63eXOhJh1S4UD-148YA.png)

**Costs (March 24, 2020):**

Active storage: $0.020 per GB.

Long-term storage: $0.010 per GB. If a table is not edited for 90 consecutive days, the price of storage for that table automatically drops by approximately 50 percent.

Streaming Inserts: $0.010 per 200 MB. You are charged for rows that are successfully inserted. Individual rows are calculated using a 1 KB minimum size.

Queries (on-demand): First 1 TB per month is free. $5.00 per TB

[Pricing | BigQuery: Cloud Data Warehouse | Google Cloud](https://cloud.google.com/bigquery/pricing)

Now, what you are really interested in:

**Examples:**

1. Let’s start with the simple one. Loading a CSV.

Before loading a CSV, let’s review some important concepts:

1.1. Schemas: BigQuery allows you to specify a table’s schema when you load data into a table, and when you create an empty table.

When you specify a table schema, you must supply each column’s name and data type. You may optionally supply a column’s description and mode.

_A column name cannot use any of the following prefixes:_

- _\_TABLE\__
- _\_FILE\__
- _\_PARTITION_

These are reserved name of BigQuery architecture.

1.2. Data types:

- _Integer: Numeric values without fractional components._
- _Floating point: Approximate numeric values with fractional components._
- _Numeric: Exact numeric values with fractional components._
- _Boolean: TRUE or FALSE (case insensitive)._
- _String: Variable-length character (Unicode) data._
- _Bytes: Variable-length binary data._
- _Date: A logical calendar date._
- _Datetime: A year, month, day, hour, minute, second, and subsecond._
- _Time: A time, independent of a specific date._
- _Timestamp: An absolute point in time, with microsecond precision._
- _Struct (Record): Container of ordered fields each with a type (required) and field name (optional)._
- _Geography: A pointset on the Earth’s surface (a set of points, lines and polygons on the WGS84 reference spheroid, with geodesic edges)._

1.3 Loading example:

Let’s download a CSV from any Kaggle challenge, for instance:

[COVID-19 Open Research Dataset Challenge (CORD-19)](https://www.kaggle.com/allen-institute-for-ai/CORD-19-research-challenge)

Click on:

![](https://cdn-images-1.medium.com/max/318/1*bbKCfXPvdCBioRRb6Vqe0Q.png)

From that folder get the file: all\_sources\_metadata\_2020–03–13.csv

Go to console.cloud.google.com:

Click on projects and create a new project:

![](https://cdn-images-1.medium.com/max/1024/1*1UguO6VCzH0z5gTqumNCAQ.png)

![](https://cdn-images-1.medium.com/max/540/1*df5w8htK9f0PxyT9ULtmfQ.png)

Set any name, and then go to: [https://console.cloud.google.com/bigquery](https://console.cloud.google.com/bigquery)

If you don’t a billing account you will have to set one before creating a dataset:

![](https://cdn-images-1.medium.com/max/370/1*f-A3px3CqeC29fGxkkSgmA.png)

Now, we can create a dataset:

![](https://cdn-images-1.medium.com/max/405/1*oXcv8LoxbmJQWV5wRoZboA.png)

The following overlay will appear:

![](https://cdn-images-1.medium.com/max/762/1*wBZIO_DpzYX6Ea-EjBbgBA.png)

Let’s call the dataset “coronavirus”. And the remaining options can be left in their default option. They are more related on how is the data is going to be stored.

On the left, click on:

![](https://cdn-images-1.medium.com/max/289/1*t2-Iy53h3zjIMvm0bf_p_g.png)

Now, we can click on Create Table:

![](https://cdn-images-1.medium.com/max/734/1*yDl-yhAyutiEPmjiLr40Vg.png)

Another overlay will appear:

![](https://cdn-images-1.medium.com/max/1024/1*9e9rfKMUXnH_E91N-KTE4Q.png)

So, normally we would select Create Table From: Upload. However, as our file has a size higher than 10MB, we have to upload it from Cloud Storage.

![](https://cdn-images-1.medium.com/max/1024/1*iBevTRMWf6piLFp9dUNLWg.png)

Go to [https://console.cloud.google.com/storage/create-bucket](https://console.cloud.google.com/storage/create-bucket)

Create a bucket called “datasets-any-other-unique-id”.

![](https://cdn-images-1.medium.com/max/536/1*C-KHPunaxCwyTP_dcS-3pw.png)

You can drag and drop now the file in the bucket. Btw, if it prompts an error of permissions, just reload the page.

Clicking on the file name we can get the URI of the file, we will use it to load the file in BigQuery:

![](https://cdn-images-1.medium.com/max/1024/1*_rdXoFyEgEig-gdDvAtNxQ.png)

We are going to create the dataset in BigQuery using Auto Detect Table Schema, which I don’t recommend, I won’t get all the correct data types for your columns, but it’s okay for this example:

![](https://cdn-images-1.medium.com/max/1024/1*Nl0c6L3mmQcnNug1yVdoQA.png)

Click at the bottom in Create Table. We will end with a table like this one:

![](https://cdn-images-1.medium.com/max/860/1*bDm70l3VT48Y1bBcOnhXCA.png)

Also we will be able to watch a preview of the dataset in Preview:

![](https://cdn-images-1.medium.com/max/1024/1*GaoNPbH8dZYGk2uG2gT4iw.png)

1.4. Some queries:

Let’s check which dates are available for the articles in our dataset.

```
SELECT DISTINCT(publish_time) FROM `${project_name}.coronavirus.all_sources_autoschema`
```

![](https://cdn-images-1.medium.com/max/1024/1*3yf6fNiDXxt0Yq_etbNwCA.png)

Let’s look for the word success in a abstract:

[String functions | BigQuery | Google Cloud](https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#regexp_contains)

```
SELECT
  abstract
FROM
  `${PROJECT_ID}.coronavirus.all_sources_autoschema`
WHERE
  REGEXP_CONTAINS( abstract, r"(?i:SUCCESS)")
```

![](https://cdn-images-1.medium.com/max/1024/1*dzM7MYXBKb65eMrRO1UZhQ.png)

And there are a bunch of utilities we can find there for strings.

We can also check how has the research been evolved in terms of the COVID-19:

![](https://cdn-images-1.medium.com/max/920/1*OAodfJvXsMy5ukElRpi6EA.png)

And which are the journal who have contributed more in the topic:

```
SELECT
  journal,
  COUNT(journal)
FROM
  `${PROJECT_ID}.coronavirus.all_sources_autoschema`
GROUP by journal ORDER BY COUNT(journal) DESC
```

![](https://cdn-images-1.medium.com/max/891/1*YvNyIXg1YnQpNQRJ_wmOEQ.png)

BigQuery ML:

Let’s go to:

[COVID19 Global Forecasting (Week 1)](https://www.kaggle.com/c/covid19-global-forecasting-week-1/data)

And download the data, essentialy, train.csv:

![](https://cdn-images-1.medium.com/max/1024/1*jtTLMwhL9zx1ae6UNWaz8A.png)

Load that in BigQuery as a Table:

![](https://cdn-images-1.medium.com/max/1024/1*hbpN-qcpx2FfI_GhzJo_qg.png)

Then create a Table:

Seems that we had had lucky with Auto detecting schema:

![](https://cdn-images-1.medium.com/max/1024/1*wnVV-lYzUvTfuw_vRBudFA.png)

This is the preview:

![](https://cdn-images-1.medium.com/max/1024/1*8QtWHeaItqAiCD0IEgpQ7A.png)

Let’s see what countries we have:

```
SELECT DISTINCT(Country_Region) FROM `${PROJECT_ID}.coronavirus.corona_prediction`
```

See that always before sending a query, BigQuery makes an estimate of how many data will be processed:

![](https://cdn-images-1.medium.com/max/330/1*bht443BdPlURd2Q8ciNCvw.png)

Let’s focus our analysis in Spain:

```
SELECT * FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
```

We can go to DataStudio and see how this data is behaving over the time:

![](https://cdn-images-1.medium.com/max/364/1*UIRqp63cNwgIkMis9GYhCA.png)

Select Time series chart:

![](https://cdn-images-1.medium.com/max/304/1*ksJF8_qWjtonBeHEe7_z-w.png)

On the right panel set Dimension, as date:

![](https://cdn-images-1.medium.com/max/166/1*US-MtGKzC0e6leiRnSjJcw.png)

And on metric click on Confirmed Cases and Fatalities:

![](https://cdn-images-1.medium.com/max/167/1*f_PKTi0dFKLvEsvkYF9Ysg.png)

We will obtain a chart like this one:

![](https://cdn-images-1.medium.com/max/1024/1*jzla0VP_zhKptEdb6hbWYA.png)

What if we create a model to predict the amount of Confirmed Cases over the time?

Creating a model has a bunch of parameters, but we can start with the simple one:

```
CREATE MODEL
  `${PROJECT_ID}.coronavirus.model_0`
OPTIONS
  ( MODEL_TYPE='LINEAR_REG',
    input_label_cols=['ConfirmedCases'] ) AS
SELECT
  Date,
  ConfirmedCases
FROM (
  SELECT * FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
)
```

![](https://cdn-images-1.medium.com/max/1024/1*J39C8mSJ1jliWA2Y47Ew3g.png)

![](https://cdn-images-1.medium.com/max/352/1*L2VBaOA4OXcKKyXzWPFsQA.png)

Smells like overfitting, but we can continue with this…

We can predict now using for example the same train dataset for spain:

```
SELECT Date FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
```

The query will look like this:

```
SELECT * FROM ML.PREDICT(MODEL `${PROJECT_ID}.coronavirus.model_0`, (SELECT Date FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'))
```

Let’s combine train and test and plot them, we are going to create

```
SELECT Date, predicted_ConfirmedCases AS ConfirmedCases, IF(true, 'test', 'disabled') AS DATASET FROM ML.PREDICT(MODEL `${PROJECT_ID}.coronavirus.model_0`, (SELECT Date FROM `${PROJECT_ID}.coronavirus.corona_test` WHERE Country_Region LIKE 'Spain'))
  
UNION ALL

SELECT Date, ConfirmedCases, IF(true, 'train', 'disabled') AS DATASET FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
```

As we see in the plot, we created a model that overfits perfectly of train data, but what happens after we don’t have more days? It seems pretty weird:

![](https://cdn-images-1.medium.com/max/1024/1*abLvDzSbyWVZZZxEVE419Q.png)

First, a model cannot be based only on the date, more than that probably Date is not being interpreted in the model as sequence with monotonic increment. So let’s do that again with Date as a TIMESTAMP. We will do the same queries but casting Date to TIMESTAMP.

Creating a model:

```
CREATE MODEL
  `${PROJECT_ID}.coronavirus.model_timestamp`
OPTIONS
  ( MODEL_TYPE='LINEAR_REG',
    input_label_cols=['ConfirmedCases'] ) AS
SELECT
  Date,
  ConfirmedCases
FROM (
  SELECT CAST(Date as TIMESTAMP) AS Date, ConfirmedCases FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
)
```

Metrics:

![](https://cdn-images-1.medium.com/max/316/1*G7hsxAavmRa0i8FJqtMx9w.png)

Looks better, more credible.

Now, run again both queries, only for train data:

```
SELECT Date, predicted_ConfirmedCases AS ConfirmedCases, IF(true, 'test', 'disabled') AS DATASET FROM ML.PREDICT(MODEL `${PROJECT_ID}.coronavirus.model_timestamp`, (SELECT CAST(Date as TIMESTAMP) AS Date FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'))
  
UNION ALL

SELECT CAST(Date as TIMESTAMP) AS Date, ConfirmedCases, IF(true, 'train', 'disabled') FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
```

Now, the plot makes more sense!

![](https://cdn-images-1.medium.com/max/1024/1*sxDl-HMJxFVClFbloHa7YA.png)

And for train and test data:

```
SELECT Date, predicted_ConfirmedCases AS ConfirmedCases, IF(true, 'test', 'disabled') AS DATASET FROM ML.PREDICT(MODEL `${PROJECT_ID}.coronavirus.model_timestamp`, (SELECT CAST(Date as TIMESTAMP) AS Date FROM `${PROJECT_ID}.coronavirus.corona_test` WHERE Country_Region LIKE 'Spain'))
  
UNION ALL
SELECT CAST(Date as TIMESTAMP) AS Date, ConfirmedCases, IF(true, 'train', 'disabled') FROM `${PROJECT_ID}.coronavirus.corona_prediction` WHERE Country_Region LIKE 'Spain'
```

![](https://cdn-images-1.medium.com/max/1024/1*0axLLcOJQhD5rrA9tnzjwQ.png)

We should submit that on Kaggle and maybe become rich! I’m kidding, we need still a lot of work here.