สรุปคอร์ส : Achieving Advanced Insights with BigQuery จาก Coursera

สวัสดีทุกๆ คนครับ วันนี้เราจะมาต่อกันกับคอร์สที่ชื่อว่า Achieving Advanced Insights with BigQuery ซึ่งนับว่าเป็นคอร์สที่ 3 ใน 4 คอร์ส จาก From Data to Insights with Google Cloud Platform Specialization แล้วนะ และเหมือนเช่นเคย เพื่อนๆ ยังสามารถย้อนกลับไปอ่านบทความที่แอดได้เขียนไว้ตั้งแต่คอร์สแรกตามลิงค์ด้านล่าง

โดยคอร์สนี้จะเกี่ยวกับการใช้ SQL, BigQuery Schema concept และวิธีการทำงานเพื่อให้ได้ Advanced Insights รวมถึงการ Unpack nested fields จาก ARRAY และ STRUCTs อีกด้วย เพื่อไม่เป็นการเสียเวลา เรามาเริ่มจาก Module 10 ไปพร้อมๆ กันเลย

Module 10 : Advanced Functions and Clauses

แอดอยากให้ลองทบทวน Functions บน SQL ที่เราได้เรียนไปก่อนหน้านี้กันสักนิด

  • การทำงานกับ String โดยการใช้ FORMAT()
  • Aggregation Functions SUM(), COUNT(), AVG(), MAX()
  • การปรับเปลี่ยน Data Type CAST()
  • การทำงานกับ Date PARSE_DATETIME()

ทีนี้เราจะมาต่อที่ Functions อื่นๆ กันบ้าง

Statistical Functions

Standard Deviation

ใน BigQuery เราสามารถเขียน SQL เพื่อคำนวนหาค่าสถิติได้ เช่น ค่า Standard Deviation หรือที่เราเรียกกันว่า ส่วนเบี่ยงเบนมาตรฐาน โดยใช้ Syntax แบบนี้ STDDEV() ส่วนเบี่ยงเบนมาตรฐาน ในทางสถิติศาสตร์ คือ การวัดการกระจายแบบหนึ่งของกลุ่มข้อมูล

ลองมารันใน bigquey-public-data กันดีกว่า โดยเราจะเลือก dataset ที่ชื่อว่า irs_990_2017

Details of irs_990_2017

สมมุติว่าเราต้องการจะหาส่วนเบี่ยงเบนมาตรฐาน เพื่อดูการกระจายตัวของจำนวนพนักงาน ใน Field ที่ชื่อว่า noemplyeesw3cnt

SELECT
  STDDEV(noemplyeesw3cnt) AS stdev_employee_count
FROM
  `bigquery-public-data.irs_990.irs_990_2017`

เท่านี้ก็ได้ส่วนเบี่ยงเบนมาตรฐานกันแล้ว

Using STDDEV in BigQuery

Correlation

หากเราต้องการหาค่า Correlation เพื่อดูความสัมพันธ์ของตัวแปร ใน BigQuery ก็ทำได้เช่นกัน โดยใช้ Syntax หน้าตาแบบนี้ CORR(Field1, Field2) และเจ้า Correlation หรือที่เรียกกันว่า ค่าสหสัมพันธ์ เป็นค่าที่ใช้ในการดูทิศทางความสัมพันธ์ระหว่างตัวแปร 2 ตัว โดยมี Correlation Coefficient (r) หรือ ค่าสัมประสิทธิ์สหสัมพันธ์ เป็นตัวบอกถึงความสัมพันธ์นี้

โดยจะมีค่าอยู่ระหว่าง -1.0 ถึง +1.0 เราสามารถวิเคราะห์ออกมาได้ 3 รูปแบบ คือ ค่าใกล้ 1.0 หมายความว่าตัวแปรทั้ง 2 ตัวมีความสัมพันธ์เชิงบวก (Positive correlation), ค่าใกล้ -1.0 หมายความว่าตัวแปรทั้ง 2 ตัวมีความสัมพันธ์ในเชิงลบ (Negative correlation) และค่าเข้าใกล้ 0 แสดงว่าตัวแปรทั้ง 2 ตัวไม่มีความสัมพันธ์กันเลย

นอกจากทิศทางความสัมพันธ์ +/- ยังสามารถบอกถึงระดับความสัมพันธ์ได้อีกด้วย เช่น ตัวแปรสองตัวที่มีความสัมพันธ์มากหรือน้อย ภาษาอังกฤษเราใช้คำว่า magnitude หรือ strength ยิ่งค่า correlation มีค่าเข้าใกล้ |1| มากเท่าไหร่ (absolute) ความสัมพันธ์จะยิ่งสูงมากขึ้นเท่านั้น ในกรณีที่ r = |1| เราเรียกว่า “perfect correlation” มาลองดูเกณฑ์การวัดระดับค่า r ที่นักสถิตินิยมใช้ในตารางด้านล่าง (อ้างอิงจาก DataRockie)

Absolute rInterpretation
0.1 – 0.3small
0.3 – 0.5medium
0.5 – 1.0large
Absolute r and Interpretation by DataRockie

หากว่าวันนี้เราอยากจะหาความสัมพันธ์ระหว่างรายได้ totprgmrevnue กับรายจ่าย totfuncexpns

SELECT
  CORR(totprgmrevnue, totfuncexpns) AS corr_rev_expense
FROM
  `bigquery-public-data.irs_990.irs_990_2017`

จะเห็นได้ว่า Correlation ระหว่างรายได้กับรายจ่าย เข้าใกล้ 1.0 หมายถึง ยิ่งรายได้มากก็จะมีรายจ่ายมากตามไปด้วย

Using CORR in BigQuery

Approximate Aggregate Functions

เจ้า Function นี้ จะช่วยให้เราประมาณค่าจำนวนของ Data ที่มีอยู่ใน Data set ได้ โดยจะมี Syntax ตามนี้ APPROX_COUNT_DISTINCT() เราลองมาใช้ Function นี้เปรียบเทียบกับ COUNT(DISTINCT) กันดู

SELECT
  APPROX_COUNT_DISTINCT(ein) AS approx_count, #นับแบบคร่าวๆ
  COUNT(DISTINCT (ein)) AS count #นับโดยละเอียด
FROM
  `bigquery-public-data.irs_990.irs_990_2017`

จะเห็นว่าผลที่ได้มีความแตกต่างกันนิดหน่อย

APPROX_COUNT_DISTINCT vs COUNT(DISTINCT)

ข้อดีของมันอยู่ที่เมื่อเราต้องทำงานกับ Data จำนวนมากหลาย Petabytes หากเราใช้ COUNT(DISTINCT) ต้องใช้เวลาในการประมวลผลมาก แต่เจ้าตัว APPROX_COUNT_DISTINCT จะประมวลผลได้เร็วกว่า ซึ่งผลที่ออกมาค่อนข้างใกล้เคียงกัน เราอาจจะพอหยวนๆ กับ Accuracy ที่ไม่จำเป็นต้องเป๊ะ แต่ได้ผลที่รวดเร็ว

ลองใช้กับ bigquery-public-data ที่ชื่อว่า github_repos ในตาราง contents ซึ่งมีขนาด 2.3 TB

Details of github_repos.contents

ใช้ APPROX_COUNT_DISTINCT() เพื่อนับจำนวนแถวแบบเร็วๆ ใช้เวลา 1 วินาที ในการ Run query

APPROX_COUNT_DISTINCT

แต่พอลองใช้ COUNT(DISTINCT) จะเห็นว่าใช้เวลาในการ Run query เยอะกว่ากันหลายเท่าตัว จาก 1 วินาที เป็น 4.4 วินาที

APPROX_COUNT_DISTINCT vs COUNT(DISTINCT)

Window Functions

หลังจากเรารู้เกี่ยวกับ Standard syntax ไปแล้ว ลองมาดูการเขียน SQL เพื่อทำการจัดอันดับ หรือการหาหมายเลขของ Row กันดีกว่า ลองมาดูตัวที่น่าสนใจของ Window Functions

Window Functions by Google Cloud

แอดจะอธิบายเจ้าตัว RANK() ที่ปกติมักใช้กันบ่อยๆ เรามีตารางพนักงาน ที่มี Field อยู่ 3 Fields คือ

  1. firstname
  2. department
  3. startdate
Employee table by Google Cloud

โจทย์ของเราก็คือ เราอยากจะจัดลำดับอายุของพนักงาน โดยแบ่งตาม Department

  • ขั้นตอนแรก เราต้องแบ่งตารางออกเป็น 2 ส่วน แยกตามแผนก คล้ายๆ กับการทำ Group By ที่เรียกว่า PARTITION BY
  • ขั้นที่สอง ทำการเรียงลำดับตามอายุงาน คือเรียงตาม startdate โดยการทำ ORDER BY
  • ขั้นที่สาม ใส่หมายเลขอันดับเข้าไปด้วย RANK()

RANK()

จากสามขั้นตอนด้านบน การใช้ RANK() มีส่วนประกอบอยู่ 3 ส่วน คือ

  • RANK() OVER
  • PARTITION BY
  • ORDER BY
How the RANK() function processed by Google Cloud

Syntax ก็จะหน้าตาแบบนี้

SELECT firstname, department, startdate,
  RANK() OVER ( PARTITION BY department ORDER BY startdate ) AS rank
FROM Employees

User-Defined Function (UDF)

ใน BigQuery ก็สามารถเขียน Function เองได้ตามที่เราต้องการ เหมือนกับภาษาอื่นๆ เช่น R, Python โดยจะมี Syntax หน้าตาแบบนี้

  • CREATE TEMPORARY FUNCTION : เป็นการบอกว่าเราจะสร้าง Function ใหม่ และกำหนดว่าจะรับ Parameters กี่ค่า มีได้ตั้งแต่ 0 เป็นต้นไป
  • RETURNS [data_type] : เป็นการเจาะจงว่าผลลัพธ์จะคืนค่าเป็น Data type ประเภทไหน
  • LANGUAGE [language] : เป็นการเจาะจงว่า Function นี้เป็นของภาษาอะไร
  • AS [external_code] : เป็นการบอกว่า Function นี้จะรันด้วย code แบบไหน

แอดลองสร้างตารางง่ายๆ ขึ้นมา 1 ตาราง ใน Google sheet แล้ว Import table เข้าไป โดยมีรายชื่อคนแค่ Field เดียว

ทีนี้เรามาลองเขียน Function Greeting เพื่อให้ ออกมาเป็น Hello, ชื่อคน เรียงกันไปเรื่อยๆ

CREATE TEMPORARY FUNCTION greeting (a STRING)
RETURNS STRING
LANGUAGE js AS """
   return "Hello, " + a + "!" 
""";

เมื่อ Create Function เรียบร้อยแล้วลองใช้ SQL รันออกมาว่าได้ผลแบบที่ต้องการมั้ย

SELECT
  greeting(string_field_0) AS everyone
FROM
  `propane-atrium-285914.friends.Test`
UDF in BigQuery

ข้อเสียของการใช้ User-Defined Function คือ Query สามาราถใช้พร้อมกันได้แค่ 6 Query เท่านั้น จะเห็นว่ากระทบต่อ Performance อย่างชัดเจน เพราะอย่างที่บอกไปในบทความก่อนๆ โดยปกติแล้วถ้า Query ทั่วไป จะรันพร้อมกันได้ถึง 50 Query

Sub-query

Sub-query คือ การเขียน Query ซ้อน Query โดยจะประมวลผลเรียงจาก Query ที่อยู่ด้านในสุดก่อน แล้วค่อยเรียงการประมวลผลออกมาตามลำดับ

ประโยชน์ของ Sub-query

  • สามารถสร้างตารางชั่วคราวเพื่อใช้ในการ Query ต่อไปได้จากจากตารางที่สร้างขึ้น
  • ทำให้เขียน Query เพื่อตอบโจทย์ในส่วนที่ซับซ้อนมากขึ้น

ลองใช้ Sub-query เพื่อแก้ปัญหาดูสักเคส แอดใช้ bigquery-public-data ที่ชื่อว่า stackoverflow ในตาราง posts_questions เป็นข้อมูลเกี่ยวกับ posts ต่างๆ ที่คนเข้ามาถามกันใน stackoverflow

Details of stackoverflow.posts_questions

สังเกตจาก Schema จะเห็นว่ามีข้อมูล ค่อนข้างหลาย Fields

Schema of stackoverflow.posts_questions

ตัวอย่างข้อมูลหน้าตาจะประมาณนี้ (จริงๆ แล้วยังมีอีกหลาย Fields แต่ว่า Text จาก Fields title, body มันกินพื้นที่ไปเยอะเลย)

Preview of stackoverflow.posts_questions

โจทย์ของเราคือ อยากได้ข้อมูล Post ที่เกี่ยวกับ SQL หรือ BigQuery ที่มียอด views มากกว่า 1,000 ลองมาเขียนโค้ดกันเลย

ขั้นตอนแรกแอดจะหา id ของ Posts ซึ่งในที่นี้เป็นตัว Primary key จากการใช้ WHERE เพื่อ Filter ค่าที่เราจะเอา และใช้ LIKE เข้ามาช่วย

SELECT id
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE
  LOWER(title) LIKE '%sql% #เลือกชื่อ Post ที่มีคำว่า sql
  OR LOWER(title) LIKE '%bigquery' #เลือกชื่อ Post ที่มีคำว่า bigquery

จากนั้นเราก็ทำการ SELECT ข้อมูลทุก Fields ที่มี id ตรงตามเงื่อนไขนี้ และเพิ่มเงื่อนไขของยอด view เข้าไป

SELECT *
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE
  id IN (
  SELECT id
  FROM `bigquery-public-data.stackoverflow.posts_questions`
  WHERE
    LOWER(title) LIKE '%sql%'
    OR LOWER(title) LIKE '%bigquery')
  AND view_count > 1000
Results from sub-quuery

งงกันมั้ยเอ่ย พูดง่ายๆ ก็คือ เราเขียน Query เพื่อลด Scope ของ Data ลง โดยจะเหลือแค่ id ของ Post ที่มีคำว่า sql และ bigquery จากนั้นเขียน Query อีกชุดนึงเพื่อดึง Data ทั้งหมดของ Post id ที่ถูก Scope ลงมาจากเดิมแล้วนั่นเอง เพื่อนๆ สามารถประยุกต์ใช้ Sub-query กับการ JOIN เพื่อเพิ่มความทรงพลังในการ Query ได้อีกด้วย

**Noted : Sub-query สามารถใช้ได้ทั้ง 3 statements SELECT , FROM, WHERE อ่านเพิ่มเติม ที่นี่

CTE’s (Common Table Expressions)

Common Table Expressions คือ การสร้างตารางแบบชั่วคราวไว้ใช้เพื่ออ้างอิงในการ Query ซึ่งจะว่าไปแล้วก็คล้ายๆ กับ Concept sub-query ด้านบนเหมือนกัน ส่วนประกอบของ CTE’s คือ Syntax ที่ชื่อว่า WITH และ AS

เราลองใช้โจทย์เดียวกันกับข้างบน คือ เราอยากได้ข้อมูล Post ที่เกี่ยวกับ SQL หรือ BigQuery ที่มียอด views มากกว่า 1,000

ก่อนอื่นเราสร้างตาราง Temporary ก่อนด้วยการใช้ CTE

WITH
  Postsql_bq #ตั้งชื่อตาราง
AS (
  SELECT id AS pid
  FROM `bigquery-public-data.stackoverflow.posts_questions`
  WHERE
    LOWER(title) LIKE '%sql%'
    OR LOWER(title) LIKE '%bigquery') #เงื่อนไขของตาราง ใช้ query จาก sub-query ได้เลย

หลังจากนั้นก็มา Query แต่ครั้งนี้จะเพิ่ม Syntax INNER JOIN เข้ามา เพื่อเป็นการ JOIN Primary key ระหว่าง 2 ตาราง คือ pid ของตาราง Postsql_bq และ id ของตารางหลัก

SELECT *
  FROM `bigquery-public-data.stackoverflow.posts_questions` AS a
  INNER JOIN Postsql_bq ON a.id = Postsql_bq.pid #JOIN primary key
  WHERE a.view_count > 1000  

ผลออกมาเหมือนกันเป๊ะ แต่ใช้เวลาเร็วกว่านิดหน่อย

Results from CTE’s

ข้อดีของ CTE’s คือ เราสามารถใช้ตารางนี้ไปได้เรื่อยๆ จนกว่าเราจะปิด BigQuery ได้เลย แต่หากเป็นตารางที่ต้องใช้ในทุกๆ วัน แอดแนะนำให้ Create View จะเหมาะสมกว่าจ้า


ก่อนไป Module ถัดไป พักสายตากันสักแปป

penguins on water during daytime
Photo by Long Ma on Unsplash

Module 11 : Schema Design and Nested Data Structures

หลังจากที่มึนๆ กับ SQL มาสักพัก เราจะมาแวะเรียนเกี่ยวกับทฤษฎีและพัฒนาการของ Database กันสักหน่อย ลองมาดูตัว bigquery-public-data ที่ชื่อว่า irs_990_2015 ซึ่งเป็นข้อมูลทางบัญชีที่เกี่ยวกับรายรับรายจ่ายต่างๆ มาลองหาวิธีที่เหมาะสมในการออกแบบ Schema เพื่อจัดการเก็บ Data กันเลย

Traditional Relational Database Architecture

Original irs_990_2015 by Google Cloud

Option 1 : Add each Expense field as a New Column

เอา Dimensions ต่างๆ ขึ้นมาเป็น Fields หรือ คอลัมน์ โดยแต่ละ Record จะมีค่า ein (Employer Identification Number) ที่ไม่ซ้ำกัน

irs_990_2015 in BigQuery by Google Cloud

ดูแบบเผินๆ ก็ค่ดูอนข้างเป็น Structure ดีแล้ว แต่ปัญหามันอยู่ตรงที่ว่า ถ้าสมมุติในปี 2016 มีประเภทของรายจ่ายที่เพิ่มขึ้นจากปี 2015 สัก 10 Fields เราจะทำยังไงดี ? ก็ต้องไปปรับเปลี่ยน Schema เลยใช่มั้ย ? ถ้าเราจะใช้ UNION กับตารางในปีก่อนๆ ก็จะเจอปัญหาที่คอลัมน์ไม่เหมือนกันอีก

ปัญหาหลัก คือ แล้วเมื่อไหร่ตารางจะนิ่ง บางปีอาจจะมี Fields น้อยลงหรือเพิ่มขึ้น การที่เราต้องคอยเปลี่ยนแปลง Schema ตลอดเวลา ถือว่าเป็นการออกแบบ Schema ที่แย่ ทางที่ดีคือเราต้องทำให้จำนวนของ Fields ที่เราต้องการเก็บมีความยืดหยุ่น ตอนนี้เห็นได้ชัดแล้วว่าการเก็บ Data แบบ WIDE table นั้นไม่สามารถ Scalable ได้

Option 2 : Break Out Expenses into another Lookup Table

แยกค่าใช้จ่ายแต่ละประเภทออกจากกันซะเลย แทนที่จะเก็บ Data ทุกอย่างไว้ในตารางเดียว จากตัวอย่างก็แยกออกมาเป็น 3 ตาราง

  • Organization : มี Primary Key เป็น Company ID เก็บข้อมูลรายละเอียดบริษัท
  • Historical Transactions : มี Primary Key เป็น Company ID และมี Foreign Key เป็น Expense Code เก็บข้อมูลรายจ่ายของบริษัท
  • Code Lookup Tables : มี Expense Code เป็น Primary Key เก็บข้อมูลชนิดของรายจ่าย

ด้วยวิธีนี้ เราจะสามารถเพิ่มจำนวนของประเภทรายจ่ายได้แบบไม่ต้องกังวลเรื่อง Schema เลย เพราะเป็นการเพิ่มจำนวน Row เท่านั้น

Break Out Expenses into another Lookup Table by Google Cloud

ซึ่งกระบวนการแบบนี้ใน Database เราเรียกกันว่า Normalization เป็นส่วนหนึ่งของทฤษฎีทาง Database คือการแตกข้อมูลออกจากตารางที่เก็บข้อมูลเป็นจำนวนมากไว้ แต่ทุกๆ ตารางที่แตกออกมาต้องมีความสัมพันธ์กัน

Normalization Benefit

Scalable Individual Tables คือ เราสามารถเพิ่มจำนวนข้อมูลของแต่ละตารางได้ตามที่เราต้องการ ต่อให้ปีใหม่ๆ จะมีประเภทรายจ่ายเพิ่มขึ้นมามากน้อยแค่ไหนเราก็ไม่หวั่นนนน

Scalable Individual Tables by Google Cloud

Normalization Drawback

JOINs are now a Necessity คือ เมื่อแยกได้.. ก็รวมได้เหมือนกัน เราสามารถเขียน Query โดยใช้การ JOIN เพื่อรวมข้อมูลจากตารางต่างๆ กลับมาเป็นตารางเดิมได้

JOINs are now a Necessity by Google Cloud

BigQuery Architecture

มี 3 Key Innovations ที่สำคัญคือ

1. Column-Based Data Storage

Columns, Records และข้อมูลต่างๆ ที่จริงแล้ว ถูก compressed แยกแต่ละ columns และเก็บอยู่ที่ Massive hard drive ใน cloud เรียกว่า Google Colossus เป็น Storage layer ตัวล่าสุด ทีนี้เราลองมาดูการเก็บข้อมูลแบบ Column-Based กัน

หากเป็น Traditional Database ข้อมูลจะถูกเก็บเป็นรายแถวเหมือนกับรูปด้านซ้าย ซึ่งส่งผลให้การทำงานของ Query จำเป็นต้องไปหาทุกๆ Columns ทำให้มี Performance การ Query ค่อนข้างต่ำ

แต่ Google ได้เป็นผู้บุกเบิกการเก็บข้อมูลแบบ Column และตีพิมพ์ไว้ในชื่อ Dremel สมัยปี 2010 ทำให้เราได้วิธีการบีบอัดข้อมูลเพื่อเก็บไว้ใน Database แบบใหม่ และมี Performance การ Query ที่เร็วขึ้นมาก เพราะไม่จำเป็นต้องไปไล่หาทุก Columns กล่าวคือ

  • การเก็บข้อมูลที่มีความสัมพันธ์กันจะวนลูปน้อยลง
  • Columns สามารถบีบอัดข้อมูลของตัวเองได้
  • สามารถเข้าไปหาข้อมูลในเฉพาะ Columns ที่เราสนใจโดยไม่ไปแตะ Columns ทั้งหมด
Oriented Storage by Google cloud

2. Break Apart Tables into Pieces

ตารางข้อมูลไม่ได้ถูกเก็บต่อกันไปเรื่อยๆ แบบตึกที่สูงมากๆ ตึกเดียว แต่มันถูกแยกออกเป็นตารางเล็กๆ มากมาย เมื่อข้อมูลถูกเรียกใช้จะมีการทำงานกันแบบ parallel เพื่อส่งข้อมูลกลับมายังผู้ใช้งานได้ ไม่ว่าข้อมูลในตารางจะมีมากแค่ไหนก็ไม่เป็นปัญหาเพราะจะถูกแบ่งออกภายหลังอยู่แล้ว โดยจะถูกแบ่งออกเป็น Chunks เช่น Chunks ละ 100 MB หรือบางทีอาจจะเล็กกว่านั้นก็ได้ ซึ่งเราจะเรียกแต่ละส่วนว่า Different Shard

Breaks Apart Data into Smaller Shards by Google Cloud

ลองมาดูการทำงานของ BigQuery engine แบบชัดๆ กันสักหน่อย (ดูภาพปลากรอบด้านล่างตามไปด้วยน้า) การทำงานของ BigQuery จะแตกแขนงการทำงานร่วมกันออกเป็น tree of work ดูอย่าง Syntax ในภาพที่ต้องการจะเอาข้อมูล Company โดยเรียงลำดับตามชื่อ Company

ในการ Query 1 ครั้ง เช่น Q1 ถือว่าเป็นงานชิ้นหนึ่งที่ถูกส่งกระจายให้ Workers แต่ละคน ในตัวอย่างจะมี Workers ทั้งหมด 3 คน Worker 1 อาจจะทำการ SELECT คอลัมน์ Worker 2 ทำการ JOIN table และ Worker 3 ทำการ GROUP BY โดยในการทำงานจะต้องเข้าไปจอง Slot ของ Worker ก่อน และหากงานที่ Worker 1 ทำนั้น ต้องการข้อมูลจาก Worker 2 งานของ Worker 1 จะถูกส่งให้ Worker 2 ได้ โดยเรียกวิธีการแบบนี้ว่า Shuffling of data หรือ Shuffle Step

BigQuery Automatically Pieces it All Back Together for Queries by Google Cloud
  • มี 2,000 Workers เพื่อรองรับการทำงานหลายๆ Query พร้อมกัน (on-demand tier) ซึ่งเราสามารถกำหนดได้จากส่วนของ user groups
  • “Fairness model” เพื่อการแบ่งใช้งาน Resources อย่างเท่าเทียม

3. Store Nested Fields within a Table

นอกจาก Relational Table แล้ว BigQuery ยังสามารถเก็บข้อมูลที่มีความสัมพันธ์แบบ Parent-child อยู่ในตารางเดียวกันได้ด้วย โดยจะเป็นข้อมูลที่เก็บลึกลงไปเป็นชั้นๆ ที่เรียกว่า Nested and repeated rows

Introducing Nested and Repeated Fields

ลองย้อนดูกันตั้งแต่ Normalized concept เราแยกตารางออกมาจากตารางเดิม เพื่อเพิ่มความสามารถในการเพิ่มจำนวน Rows แทน Columns จากนั้นเราก็ Denormalized ด้วยการ JOIN ทีนี้เราลองมาดูกันว่า Repeated concept จะเป็นอย่างไร

หากลองดูในรูปด้านล่าง Repeated หน้าตาจะประหลาดๆ นิดนึง คือมีข้อมูล Sub ย่อยลงไปอีกชั้นเหมือนการกด Tab บน Keyboard จาก cities_lived (repeated) เป็น Field ที่เก็บประวัติที่อยู่ของคนคนนี้เอาไว้ว่าเคยอยู่ที่ไหนมาแล้วบ้าง

Three concept in BigQuery by Google Cloud

มาดูตัวอย่าง Dataset ของ Transactions ของบริษัทต่างๆ ที่เก็บข้อมูลแบบ Nested Schema

Nested Schema for highly scalable queries

หน้าตาของ Nested Schema ก็เป็นแบบการกด Tab จริงๆ คือแหว่งเข้าไปเลย 555+ พูดง่ายๆ มันเหมือนกับการเก็บข้อมูลเฉพาะของแต่ละบริษัท โดยเก็บเป็นราย transaction ของการจ่ายเงิน การเก็บข้อมูลแบบนี้ ไม่จำเป็นต้องใช้ JOIN เลย เพราะสามารถเก็บข้อมูลทั้งหมดย่อยลงไปได้เป็นชั้นๆ ภายใต้ Singular records เช่น บริษัท NY Association Inc. แค่ Record เดียวสามารถมี Child ได้ถึง 3 Records คือ ข้อมูลในแถบสีน้ำเงินอยู่ภายใต้ Row เดียวกัน ดังนั้นจากรูปตัวอย่าง จะมีทั้งหมด 2 Rows ได้แก่ NY Association Inc. และ ACME Co.

ประโยชน์ของ Nested Schema

  • ลด Cost ของการ Joins เพราะมี Internal Joins ผ่าน child อยู่แล้ว
  • หากใช้ SELECT(DISTINCT Company ID) ในช่องสีเทาๆ จะไม่ถูกคิด Performance ในการ Run query

Working with Repeated Fields

Introducing Arrays and Structs

ARRAYs

Arrays คือ การเก็บข้อมูลรูปแบบหนึ่งเป็น ordered lists มีจำนวนของข้อมูลได้ตั้งแต่ 0 เป็นต้นไป แต่ทุกๆ ค่าใน Arrays ต้องมี Data Type เหมือนกัน โดยจะแบ่งข้อมูลด้วย comma เช่น

[ 0.1, 0.2, 0.3, 0.4] เป็น Float เหมือนกันทั้งหมด หรือจะเป็น Arrays ของผลไม้ในรูปด้านล่าง

Array of fruits by Google Cloud

เรามาลองสร้าง Arrays ของผลไม้บน BigQuery กันเลยดีกว่า

SELECT
['raspberry','blackberry','strawberry','cherry'] #ใส่ข้อมูลใน Array
AS fruit_array #ตั้งชื่อ Array

ผลที่ได้จะออกมาหน้าตาแบบนี้ สังเกตได้ว่ามันมีแค่ 1 Row เท่านั้น หน้าตาคล้ายๆ กับตัวอย่าง Nested Schema ของ Transactions ด้านบนเลย

Arrays in BigQuery

เราสามารถตรวจสอบขนาดของ Array หรือจำนวน items ที่อยู่ใน Array ได้ โดยใช้คำสั่งนี้

WITH fruits AS (
SELECT
['raspberry','blackberry','strawberry','cherry']
AS fruit_array
)

SELECT ARRAY_LENGTH(fruit_array) AS array_size #ใช้ ARRAY_LENGTH() เพื่อนับจำนวนข้อมูลที่อยู่ใน Array
FROM fruits;

ผลที่ได้จะเป็นจำนวน items ใน Array

Using ARRAY_LENGTH() to count items inside array

BigQuery จะมอง Array เป็น Flattened array และมอง Field ทั่วไปเป็น Normal Field ลองดูตัวอย่าง เราจะลองเพิ่มลูกค้าเข้าไปอีกสัก 1 คน

SELECT
['raspberry','blackberry','strawberry','cherry'] AS item,
'Michael' AS customer

ผลที่ได้จะออกมาแบบนี้

Michael จะกลายเป็น Parent record ที่มี Child records เป็น item ที่เค้ามีอยู่ ซึ่งโดยปกติแล้วข้อมูลแบบนี้จะถูกแยกเป็นตาราง Customers กับตาราง Orders และตาราง Details ทีนี้เราลองมาดูกันว่าเราจะ access elements ที่อยู่ใน Array ได้ยังไง ?

UNNEST()

UNNEST คือ Query ที่ใช้กระจาย Elements ใน Array ออกมา และ Return ค่าเป็นราย Row

สมมุติว่าเราจะ UNNEST item ของคุณ Michael จากตัวอย่างด้านบนออกมาเป็น Syntax หน้าตาก็จะได้ประมาณนี้

SELECT
items,
customer_name
FROM
UNNEST(['raspberry','blackberry','strawberry','cherry']) AS items #ใช้ UNNEST ใน FROM statements
CROSS JOIN
(SELECT 'Michael' AS customer_name)

อธิบายอีกทีเพื่อไม่ให้งงจนเกินไป ขั้นแรกเรา SELECT items, customer_name เพื่อให้ทั้ง 2 Fields จับคู่กันก่อน จากนั้น Unpack Array ของ items โดยใช้ UNNEST() และใช้คู่กับ CROSS JOIN ซึ่งเป็นการ JOIN ค่าเข้าด้วยกันทั้งหมดของ items และ customer คำสั่งนี้จะทำการ Copy ชื่อ Michael ตามไปทุก items

Results from UNNEST()

นอกจาก UNNEST ก็ยังมี ARRAY_AGG เพื่อใช้ Aggregate Arrays หรือการสร้าง Arrays นั้นเอง สมมุติว่าเราสร้างตารางผลไม้ 3 rows

Create fruits table

จากนั้นเราอยากสร้างเป็นตะกร้าผลไม้ ให้ผลไม้ทุกอันมาอยู่ใน Array เดียวกัน ลองใช้ ARRAY_AGG มาช่วย

SELECT ARRAY_AGG(fruit) AS
fruit_basket
FROM fruits;

เท่านี้เราก็ได้ตารางผลไม้แล้วจ้า

Create fruit basket using ARRAY_AGG

แล้วถ้าเรามีผลไม้หลายๆ ตะกร้า เราจะสามารถเลือกตะกร้าบางตะกร้าได้ไหม คำตอบคือ ได้ !! เพราะเราสามารถใช้ WHERE ร่วมกับ UNNEST ได้นั่นเอง

#สร้างตะกร้าใส่สินค้า 3 ตะกร้า
WITH
  groceries AS (
  SELECT ['apple','pear','banana'] AS basket
  UNION ALL
  SELECT ['carrot','apple'] AS basket
  UNION ALL
  SELECT
  ['water','wine'] AS basket)

#Filter เอาเฉพาะตะกร้าที่มี apple
SELECT
  ARRAY(
  SELECT items
  FROM UNNEST(basket) AS items
  WHERE 'apple' IN UNNEST(basket)) AS contain_apple
FROM
  groceries;
Using UNNEST() and WHERE

STRUCTs

Struct คือ การเก็บข้อมูลอยู่ในรูปของ Flexible Container จะมี Concept คล้ายๆ กับ Array แต่จะต่างกันตรงที่ Struct สามารถเก็บข้อมูลได้ทุกประเภทรวมถึง Array ด้วย ลองมาสร้าง Struct ใน BigQuery กันเลย

SELECT
STRUCT(31 AS age, 'Yos' AS name) #ใส่ข้อมูลลงไปใน STRUCT()

เราก็จะได้ Struct ที่มีค่า อายุ และชื่อ ซึ่งเจ้า Struct จะเก็บค่า age เป็น integer และ name เป็น string ทั้ง 2 Columns จะถูกเก็บอยู่ใน 1 Struct สังเกตได้ว่า Struct จะเก็บข้อมูลเป็น Columns จะต่างจาก Array ที่เก็บข้อมูลเป็น Rows

Create the first STRUCT

ลองสังเกตผลลัพธ์ด้านบนอีกที จะมีเจ้าตัว Prefix หน้าตาประหลาดที่เป็น f0_ อยู่ทั้งสอง Columns ทำไมถึงเป็นอย่างนั้น ? คำตอบก็คือ เราไม่ได้สร้าง Alias ได้ใน Query นั่นเอง ลองเพิ่ม Alias เข้าไปแล้วลองดูผลลัพธ์ใหม่ พูดง่ายๆ คือการใส่ Alias เข้าไปหลัง Query เสมือนเป็นการตั้งชื่อ STRUCT นั่นเอง

Create the STRUCT with alias

ทีนี้ลองใส่ Array ของ Skills ลงไปใน Struct กันดูบ้าง

SELECT
  STRUCT(31 AS age,
    'Yos' AS name,
    ['SQL', 'Google Sheet','Google Analytics'] AS skills) #เพิ่ม Array ลงไปเป็น Value ได้
    AS customers

เราก็จะได้ Struct ที่มี Array อยู่ข้างในอีกที หรือมีเจ้า Nested field ใน Struct นั่นเอง เริ่มซับซ้อนไปกันใหญ่ 555+

แล้วในทางกลับกัน Array สามารถใส่ข้อมูลที่เป็น Struct ได้มั้ย ?? คำตอบคือ ได้ !! เรียกได้ว่าซับซ้อน แล้วก็ซ้อนเงื่อนกันไปอีก เรามาลองสร้าง Array ที่มี Struct ที่มี Array กันเถอะ งงมั้ย 5555+

SELECT [
  STRUCT(31 AS age,
    'Yos' AS name,
    ['SQL', 'Google Sheet','Google Analytics'] AS skills),
  STRUCT(29 AS age,
    'Jane' AS name,
    ['SQL', 'MS Excel','Alteryx'] AS skills),  
  STRUCT(25 AS age,
    'Smith' AS name,
    ['JavaScript', 'Google Sheet','Google Tag Manager'] AS skills)
]        
    AS members

และผลที่ได้ก็จะเป็นแบบนี้ คือข้อมูลทั้งหมดอยู่ภายใต้ 1 Row เท่านั้น !! ลองมาทวนกันอีกที

SELECT ARRAY[ STRUCT [ARRAY], STRUCT [ARRAY], STRUCT [ARRAY] ]

ยังๆ ยังไม่พอ เราลองมา Filter member ที่มี skill JavaScript กันดีกว่า

#สร้าง ARRAY ขึ้นมาจาก query ก่อนหน้านี้
WITH member_skills AS (
SELECT [
  STRUCT(31 AS age,
    'Yos' AS name,
    ['SQL', 'Google Sheet','Google Analytics'] AS skills),
  STRUCT(29 AS age,
    'Jane' AS name,
    ['SQL', 'MS Excel','Alteryx'] AS skills),  
  STRUCT(25 AS age,
    'Smith' AS name,
    ['JavaScript', 'Google Sheet','Google Tag Manager'] AS skills)
]        
    AS members
    )
    
SELECT members                                     #เลือก Array
FROM member_skills AS ms                           #จากตารางที่สร้างขึ้นมา
CROSS JOIN UNNEST(ms.members) AS members           #unpack Array ของ members ออก
WHERE 'JavaScript' IN UNNEST(members.skills)       #Filter struct ของ members ที่มีค่า skills = 'JavaScript' 
Filer member contains JavaScript skill

Recap Arrays and Structs

  • Nested records บน BigQuery คือ Arrays ของ Structs
  • ใช้การ Join ภายในตาราง แทนที่จะใช้ Concept การ Join ทั่วไปของ SQL
  • UNNESTing ARRAY ของ STRUCTs นั้นคล้ายๆ กับการ join ตาราง

Module 12 : More Visualization with Google Data Studio

หลังจากในบทความก่อนหน้านี้ ทุกคนคงรู้จักกับ Data Studio กันมาพอสมควรแล้ว หรือถ้ายังอยากทบทวน Data Studio กันอีก ก็สามารถย้อนกลับไปอ่านบทความที่แอดเคยสรุปไว้ทั้ง 2 EP. เพื่อจะได้เข้าใจกันมากขึ้น อีกสัก สอง สาม สี่ รอบ ก็ได้

เพื่อนๆ คนไหนที่อ่านจบแล้ว หรือเคยใช้ Data Studio กันมาบ้างแล้ว ก็มาลุยกันต่อกับแอดได้เลย

Case Statements

CASE

CASE คือ การตั้ง Custom rule based เพื่อกำหนดการแสดงค่าให้ตรงกับเงื่อนไขที่เราต้องการ มักใช้เพื่อสร้าง Field หรือ Column ใหม่ โดยใช้เงื่อนไขจากข้อมูลที่มีอยู่แล้ว ลองดู Syntax กันก่อน

CASE
    WHEN condition1 THEN result1  #ใส่เงื่อนไขตรง condition และใส่ค่าที่จะให้แสดงใน result
    WHEN condition2 THEN result2
    WHEN conditionN THEN resultN
    ELSE result  #หลัง ELSE เป็นการใส่ค่าที่จะให้แสดงหากไม่ตรงกับเงื่อนไขที่กำหนดเลย
END [AS alias for column name]

สมมุติว่าเราต้องการสร้าง Field ที่เป็น Grade ของนักเรียน โดยแบ่งตามจำนวนคะแนนสอบ

CASE
    WHEN score > 80 THEN 'A'
    WHEN score > 70 THEN 'B'
    WHEN score > 60 THEN 'C'
    WHEN score > 50 THEN 'D'
    ELSE 'F'
END AS Grade

ก่อนอื่นแอดจะสร้าง Data Studio ขึ้นมาใหม่เพื่อให้ทุกคนเห็นภาพมากขึ้น โดยจะ Connect กับ Connector ชื่อ BigQuery โดย Billing Project ของ GCP โดยผูกกับอีเมลที่เราใช้สร้าง Data Studio เลือก Public Dataset เป็นเจ้า baseball และเลือกตารางที่ชื่อ schedules

Connect Data Studio with BigQuery

แอดสร้างตารางขึ้นมาโดยดึงเอา Dimension -> year (ปีที่แข่ง), homeTeamName (ชื่อทีมเหย้า), awayTeamName (ชื่อทีมเยือน) และ attendance (จำนวนผู้ชม) ทีนี้เราอยากจะสร้าง Dimension ใหม่ขึ้นมาชื่อ Density แล้วแบ่งเกณฑ์ของจำนวน attendance เป็น Highest, High, Medium, Low จากนั้นเข้าไปที่ ADD A FIELD

Create a table and add a field

ต่อไปก็เขียน CASE ได้เลย และจะมี Syntax validator อยู่ข้างล่าง เพื่อตรวจสอบความถูกต้องของ Syntax ให้ด้วย

Write CASE statements for creating a new dimension

และนี่คือผลที่ได้ หลังจากเราเพิ่ม Dimension ที่เราสร้างมาในตาราง

Result from CASE statement

Module 13 : Optimizing for Performance

Avoid BigQuery Performance Pitfalls

Input / Output

ต้องคำนึงถึงจำนวน bytes ที่ Read และจำนวน bytes ที่ Write ลง Storage บน BigQuery

  • กฎเหล็กที่สำคัญของการทำงานบน BigQuery คือ ไม่ควรใช้ SELECT * แต่ควรจะ SELECT เฉพาะ Field ที่ต้องการเท่านั้น
  • Denormalize Schema ด้วยการใช้ Nested และ Repeated fields แทนที่จะต้องแยก Table แล้วใช้ Primary Key มา Join กัน
  • ใช้ Wildcard + TABLE_SUFFIX สามารถย้อนกลับไปทบทวนได้ในบทความก่อนหน้านี้ คลิก

Use BigQuery native storage for the best performance !!

  • การต่อ External data connections จะไม่สามารถเก็บ cached ได้ ทำให้เมื่อเรา Run query เดิม ก็ยังคงเสียเวลาเท่าเดิม เพราะต้องดึงข้อมูลจาก External data source มาใหม่ทุกครั้ง ตรงกันข้ามกับการใช้ Dataset ที่อยู่ใน BigQuery จะมีการเก็บ cached ไว้ ถ้า Run query เดิมจะใช้เวลาน้อยลง
  • หาก External data นั้นเป็น Spreadsheet ข้อมูลจะเปลี่ยนได้แบบ Real-time ทำให้ข้อมูลเปลี่ยนแปลงได้ง่าย BigQuery จะสับสนว่าอันไหนคือ Last version ของ Spreadsheet กันแน่
  • BigQuery มีการใช้ Performance ที่ค่อนข้างหลากหลายวิธี เมื่อเราเขียน Query ยาวๆ สักอัน เรา Filter dataset หลายๆ แบบ เช่น ใช้ WHERE ต่างๆ จากนั้น BigQuery จะเอา Filter เหล่านี้ ไปทำสิ่งที่เรียกว่า “Predicate pushdown” คือ การสั่งให้ data source กรองข้อมูลตามที่ต้องการก่อน แล้วจึงส่งเฉพาะข้อมูลที่ต้องการกลับมาให้เรา การ pushdown where filter แบบนี้จะช่วยให้ทำงานได้เร็วขึ้น และลด load บน data source ได้
Data Connections flow in BigQuery by Google Cloud

Communication between slots (shuffle)

ต้องคำนึงถึงจำนวน bytes ที่ส่งต่อไปยัง stage ถัดไป หรือ Workers คนถัดไป สิ่งที่น่าสนใจ คือวิธีการที่ Workers ที่อยู่หลังบ้านคุยกันเพื่อแบ่งการทำงานในแต่ละส่วนของ Query และลงไปยัง slot ของแต่ละ Workers สิ่งที่ทำให้การทำงานง่ายขึ้นก็คือ

  • เริ่ม Filter ตารางแต่ละตารางก่อนทำการ JOINs เช่น ถ้าจำนวน Records 80% ของตารางมีค่า Null ก็ควรจะ WHERE Null ออกก่อน เพื่อประหยัด Slots ของ Workers ในการทำงานกับ Records ที่มีจำนวนน้อยลง ทำให้ลดเวลาในการคุยกันเพื่อส่งงานไปมาระหว่าง Workers อีกด้วย
  • หลายๆ Stage อาจเจอกับ Data skew ถ้ามีการทำงานคอขวดที่ Workers บางคน สามารถแก้ไขได้เบื้องต้นด้วยการ Optimize Query (มีอธิบายต่อด้านล่าง)
Communication between slots by Google Cloud

Prevent Hotspots in your Data

หลีกเลี่ยงการใช้ WITH clauses ด้วย Permanent table

เมื่อเราพูดถึงการใช้ WITH เรามักพูดกันว่าจะใช้เพื่อช่วยแบ่งส่วนของ Query ที่ซับซ้อนให้ใช้งานได้ง่ายขึ้น แต่มันก็มีอีกเหตุผล คือเราไม่ต้องการนำผลลัพธ์ที่ได้จากการ Query ไปเก็บบน Permanent Storage นั่นเอง เราลองมาดู Query กัน

Example of WITH clauses by Google Cloud

จากภาพด้านบน เราใช้ WITH เพื่อจะ Define การ Joins กันของ irs_990_2015 (เก็บข้อมูลทางบัญชีของแต่ละ Organization) กับ irs_990_ein (เก็บข้อมูล Organization details) หากเรารัน Query มากกว่า 1 ครั้ง ก็เหมือนกับเรา Join แบบนี้ใหม่ทุกครั้ง วิธีแก้ปัญหาคือ เราควรจะเก็บ Query ใน Line ที่ 6 ถึง Line 13 เป็น Permanent table เลย เพื่อดึงข้อมูลมาใช้งานทีหลังได้โดยไม่ต้องเสียเวลาในการ Join ซ้ำๆ ซึ่งจะช่วยลดความยาวของ Code และช่วยลเวลาในการรัน Query ได้อีกด้วย

ข้อควรระวังในการใช้ GROUP BY

ไม่ควร GROUP BY ด้วยการใช้ Many distinct values ยกตัวอย่าง เช่น ID Card เพราะจะทำให้มีการรันโดยละเอียดทีละ ID ซึ่งทำให้เกิดสิ่งที่เรียกว่า Forced Shuffles หรือ Forced communication steps ระหว่าง Workers ทางดีที่ควร Group ใน Scale ที่ใหญ่ขึ้น เช่น สี, จังหวัด, อำเภอ, ขนาด เป็นต้น

ระวังการเกิด Data Skew ใน Dataset

สิ่งที่ควรระวังคือการเกิดขึ้นบ่อยๆ ของค่าบางค่าใน Dataset ยกตัวอย่างเช่น สมมุติว่าเรามีข้อมูล Transaction การซื้อของ เป็นล้านๆ Records แต่ข้อมูล 99% เป็นของ Customer เพียงบางกลุ่ม เมื่อเรา Run query สิ่งที่เกิดขึ้นภายใน BigQuery จะเป็นแบบนี้

Workers 1 คนจะรับ values ทั้งหมดของ customer ที่ 1 ที่มีข้อมูลอยู่ 99% ในขณะที่ Workers คนอื่นต้องรอที่จะใช้ Slot เพื่อเสร็จสิ้นการประมวลผลข้อมูล หลังจากนั้นถึงจะรวมผลลัพธ์เข้าด้วยกันและแสดงค่าให้เราได้เห็น สิ่งนี้เราสามารถสังเกตได้จาก Query Explanation Map ที่จะแสดงค่า complete task ของแต่ละ Workers เทียบกับค่าเฉลี่ยทั้งหมดกับ Workers อื่นๆ

Query Explanation Map

Query Explanation Map คือ Features ที่ใช้แจกแจงรายละเอียดของ Query ว่ามีการทำงานกี่ Stage แต่ละ Stage มี Task อะไรบ้างใช้เวลาในการทำงานเท่าไหร่ รวมถึง Output ที่ได้ในแต่ละ Stage ด้วย

ก่อนอื่นเราลองรัน Query นี้ดู

WITH
Postsql_bq AS (
SELECT id AS pid
FROM bigquery-public-data.stackoverflow.posts_questions
WHERE
LOWER(title) LIKE '%sql%'
OR LOWER(title) LIKE '%bigquery')

####

SELECT *
FROM bigquery-public-data.stackoverflow.posts_questions AS a
INNER JOIN Postsql_bq ON a.id = Postsql_bq.pid
WHERE a.view_count > 1000

กดไปที่ Tab ชื่อ Execution details จะเจอ Query Explanation Map ตามรูปด้านล่าง

Example of Query Explanation Map

จะเห็นค่าที่น่าสนใจ 4 ค่า

  • Elapsed time: total time for the query to process
  • Slot time consumed: if the query were not processed in parallel on multiple machines, how long would it take to process
  • Bytes shuffled: Automatic in-memory data shuffling for massive parallel processing
  • Bytes spilled to disk: If data cannot be processed in memory, how much was spilled to persistent disk (usually data skew is to blame)

ซึ่งเราสามารถ Drill down ลงไปดูแต่ละ Stage อย่างละเอียดได้จากการกดเครื่องหมาย v ข้างๆ กับ Stages

จากภาพในกรอบสีแดง จะเห็นได้ว่าแต่ละ Stages มีการบอกว่า READ อะไรจาก Stage ไหน และ WRITE อะไรเพื่อส่งต่อไปยัง Stage ไหน และบอกเวลาที่ใช้รวมถึง Output ที่ได้


Module 14 : Data Access Roles

Access Roles จะแบ่งเป็น 2 ส่วน คือ BigQuery Roles และ IAM Project Roles

BigQuery Predefined roles

BQ Predefined roles by Google Cloud

IAM Project Roles

IAM Project roles by Google Cloud

Course Summary

จบกันไปแล้วสำหรับ การรีวิวคอร์ส Achieving Advanced Insights with BigQuery จาก Coursera ทีนี้เราลองมาดู Hands-on Labs ทั้งหมดในคอร์ส ที่ทำผ่าน Qwiklabs เหมือนเดิมเลย

  • Lab1 : Deriving Insights from Advanced SQL Functions
  • Lab2 : Practicing Working with Nested and Repeated Fields
  • Lab3 : Optimizing and Troubleshooting Query Performance
  • Lab4 : Run BigQuery in a Jupyter Notebook

ลองสรุปกันอีกทีว่ารอบนี้เราเรียนอะไรไปกันบ้าง

  • Module 10 : Advanced Functions and Clauses
  • Module 11 : Schema Design and Nested Data Structures
  • Module 12 : More Visualization with Google Data Studio
  • Module 13 : Optimizing for Performance
  • Module 14 : Data Access Roles

แอดว่าคอร์สนี้เนื้อหาน่าสนใจมากโดยเฉพาะ Nested Data Structures เพราะตัวแอดเองทำงานบน BigQuery โดยใช้ Dataset ของ Google Analytics ซึ่งมันมีหน้าตาแบบ Nested Data Structures พอดี เลยรู้สึกสนุกปน มึนงงเป็นพิเศษ 555+

หวังว่าบทความนี้จะมีประโยชน์ต่อทุกคนที่เข้ามาอ่านไม่มากก็น้อยนะคร้าบ รอติดตามบทความต่อไปเร็วๆ นี้

พูดคุยกันได้ที่เพจ Malonglearn – มาลองเรียน หรือติชมผ่านคอมเม้นด้านล่างเลยจ้า