Scroll ลง เพื่อดูบทความ
ไขปริศนา ความท้าทายต่าง ๆ ในการก้าวไปสู่ตำแหน่ง CTO
โดย PanJ
ในสายอาชีพ programmer/developer ตำแหน่งที่คนส่วนใหญ่คิดว่าสูงที่สุดแล้วน่าจะหนีไม่พ้น Chief Technology Officer หรือ CTO ซึ่งมีชื่อเรียกภาษาไทยเก๋ ๆ ว่าประธานเจ้าหน้าที่บริหารฝ่ายเทคโนโลยี เอาจริง ๆ แล ...
Solving BigData with BigQuery (3/3) — ใช้จริง
โดย SARIN
บทความนี้จะมีเนื้อหาเกี่ยวกับ Google BigQuery: Serverless Data Warehouse จาก Google ครับ บทความนี้เป็นเนื้อหาพาร์ทสุดท้ายจาก ซีรีส์แนะนำ Google BigQuery ของ Cleverse โดยบทความนี้จะเน้นไปที่แนวทางต่างๆ ...
Solving BigData with BigQuery (2/3) — ลองเล่น
โดย SARIN
คุณมีปัญหากับการวิเคราะห์ข้อมูลขนาดใหญ่ใช่ไหม? — ลองมาใช้ BigQuery ดูสิ 0) เกริ่นนำ หากคุณเป็นคนที่ทำงานในสายงาน Data Science หรือใกล้เคียง คุณอาจจะเคยได้ยินคนพูดถึง BigQuery มาบ้าง สรุปแบบสั้นๆเลยคือ ...
Solving BigData with BigQuery (1/3) — บทนำ
โดย SARIN
หลายๆคนอาจจะมองว่าการจัดการ Big Data เป็นเรื่องลำบาก — ตั้งแต่การวางแผนติดตั้งระบบ การนำข้อมูลเข้า จนถึงการ Query ข้อมูลแต่ละครั้งซึ่งทำได้ยากและใช้เวลานาน แถมพอใช้งานจริงก็ต้องคอยดูแลอีก วันนี้บล็อกน ...
ของโคตรดี! เมื่อแทนที่ GraphQL Backend ด้วย Graphcool!
โดย ชิน
สำหรับท่านที่ไม่เคยใช้ GraphQL มาก่อน น่าจะเคยใช้ชีวิตร่วมกับ REST มาก่อน ซึ่งตัว REST จะมีความต่างที่ชัดเจนจาก GraphQL คือ REST เราต้องกำหนด endpoint เต็มไปหมด ถ้า model เปลี่ยนไปเรื่อยๆต้องมาแก้ทีละ ...
ENGINEERING
DESIGN
CULTURE
Cleverse, a venture builder, with people who have fun building the future. If you also consider building the future a fun and meaningful purpose — let’s find a way we can work together.
121/75 RS TOWER 24th Floor
Ratchadaphisek Road
Dindaeng Bangkok 10400
Thailand
22.May.2018
โดย SARIN

Solving BigData with BigQuery (3/3) — ใช้จริง

Scroll down

บทความนี้จะมีเนื้อหาเกี่ยวกับ Google BigQuery: Serverless Data Warehouse จาก Google ครับ

บทความนี้เป็นเนื้อหาพาร์ทสุดท้ายจาก ซีรีส์แนะนำ Google BigQuery ของ Cleverse โดยบทความนี้จะเน้นไปที่แนวทางต่างๆ ในการ ลดค่าใช้จ่าย และ ข้อที่ควรคำนึงก่อนนำ Google BigQuery ไปใช้งานจริง ครับ

สำหรับคนที่อยากรู้จัก Google BigQuery และลองศึกษาการใช้งานคร่าวๆ ผู้เขียนขอ Redirect (=เชิญ) ท่านไปที่บทความเก่าๆ ของเราก่อนครับ

  • Part 1: แนะนำ Google BigQuery / ฉบับ Cleverse
  • Part 2: ลองเล่นกับ Google BigQuery / สอนรูปแบบการใช้ง่าย Google BigQuery คร่าวๆ ตั้งแต่การนำข้อมูลเข้า การค้นข้อมูล และการส่งออกข้อมูล
  • Part 3: แนวทางในการลดค่าใช้จ่าย Google Bigquery / ซึ่งก็คือบทความนี้ครับ 🙂

เกริ่นนำ

ก่อนจะพูดถึงเนื้อหาหลัก เราขอเริ่มบทความโดยพาคุณถอยกลับมาดู Pricing Model ของ Google BigQuery กันก่อน

สรุปแบบสั้นๆคือ BigQuery จะคิดเงินตามจำนวนของ Bytes ของข้อมูลที่ถูกใช้คำนวณ ในอัตรา $5 ต่อข้อมูล 1 Terabyte

ต่อจากนั้นเราจะทำการลอง Query ข้อมูลหนึ่งแถวเล็กๆ จากตาราง XXX ที่ทางบริษัทเก็บไว้บน BigQuery ให้ดูครับ

จากภาพจะเห็นว่า BigQuery จะเตือนขึ้นมาว่า Query นี้จะใช้ข้อมูล 90.1GB ในการประมวลผล.. อาจจะฟังดูตลกดี แต่ 90.1 GB ที่ว่านั้นคือขนาดของตาราง XXX ที่ทางบริษัทได้เก็บไว้ทั้งตารางนั่นเอง

ตารางสมมติ: XXX ขนาด 90.1GB

ซึ่งคิดกลับไปเป็นเงินตามข้อมูลที่กล่าวมาข้างต้น, Query เมื่อกี้จะกินเงินไปแค่:

5$/TB * 90.1GB = $0.45

(ตีเป็นเงินไทยประมาณ 14 บาท 50 สตางค์ เท่านั้นเอง..)

อาจจะฟังดูเหลือเชื่ออยู่ที่บอกว่าการค้นข้อมูลหนึ่งแถวจะเสียเงิน 14.5 บาท ซึ่งถ้าเอามาใช้แบบนี้จริงๆ ยิงรีเควสไป 25 ที ก็เท่ากับค่า CD BNK48 แผ่นนึงแล้ว.. *ซื้อไม่ทัน

ซึ่งแน่นอน ตอนใช้งานจริงเราคงไม่ทำอะไรแบบนี้แน่ๆ - ในส่วนถัดไปจะขอพูดถึงแนวทางในการลดค่าใช้จ่ายบน BigQuery ต่อไปครับ


สาเหตุ: เบื้องหลังการทำงาน BigQuery

BigQuery ใช้ระบบ Columnar Storage บนเครื่อง Cluster หลายๆเครื่อง (Distributed File System) ซึ่งทำให้การอ่านและคำนวณข้อมูลมหาศาลสามารถทำขนานกัน สเกลได้ง่าย และทำได้เร็วมาก

แต่โครงสร้างดังกล่าวทำให้ BigQuery ไม่มีระบบ Indexing เหมือน Database/Data Warehouse ทั่วไป ทำให้การ Query ข้อมูลแต่ละครั้ง ไม่ว่าจะทำกับข้อมูลส่วนไหนก็ตาม ก็ต้องเริ่มต้นจากการค้นหาจากข้อมูลทั้งตาราง

จากข้อจำกัดดังกล่าว ทำให้แนวทางการลดค่าใช้จ่ายที่เกิดจาก BigQuery สามารถทำได้สามวิธีหลักๆ ดังนี้ครับ

  • Plan A) Monitor ดูค่าใช้จ่ายที่ผ่านมาและสถิติการใช้งาน และใส่ลิมิตไว้คุมค่าใช้จ่ายไม่ให้ใช้เยอะเกินไป
  • Plan B) ลดจำนวน Query ที่ใช้ลง
  • Plan C) ลดขนาดข้อมูลที่ต้องใช้ในแต่ละ Query ลง

Plan A: Costs Monitoring & Control

ผู้เขียนขอเริ่มต้นจากการ Monitor ดูค่าใช้จ่ายที่เกิดขึ้นจากการใช้งาน BigQuery ในส่วนต่างๆ กันก่อนครับ จะได้นำข้อมูลการใช้งานไปวางแผนต่อๆไปได้ ดังนี้ครับ 🙂

Query-level costs control

BigQuery มีเครื่องมือไว้ให้เราได้ประเมินค่าใช้จ่ายของแต่ละ Query ล่วงหน้าก่อนจะทำงานจริง โดยจะวิเคราะห์จาก SQL ที่จะใช้ได้ครับ

  • หากใช้งานผ่าน Web-UI ให้กดเครื่องหมายถูกสีเขียว (Validator) แล้วตัวระบบจะแสดงจำนวนข้อมูลที่จะต้องถูกใช้งานจาก Query ก่อนจะสั่งงานจริงๆ ให้เราไปใช้ประเมินค่าใช้จ่ายได้ก่อน
  • เราสามารถคำนวณค่าใช้จ่ายได้จากการนำ Query ไปสั่ง dry-run แทนการสั่งปกติ ซึ่งจะคืนผลลัพธ์มาเป็นค่าใช้จ่ายที่ต้องเสียหาก Query ดังกล่าวถูกสั่งงานครับ

นอกจากนี้เราสามารถตั้งลิมิตไว้ได้ ว่าห้ามใช้ข้อมูลขนาดเกินเท่าไหร่ (Maximum Bytes Billed) ซึ่งหาก Query นั้นใช้ข้อมูลเกินจะถูกตัดการทำงานและไม่ถูกคิดเงิน

Project-wide costs control

เราสามารถตั้ง Billing Alert เพื่อจำกัดค่าใช้งานในระดับโปรเจคต์ หรือรายผู้ใช้แต่ละคน ได้ ไม่ให้โดนคิดเงินเราเกินที่ตั้งไว้ หรือให้ส่งอีเมล์มาแจ้งเตือนก็ได้ เช่นเดียวกับใน Product อื่นๆ ของ Google

Billing Export

เราสามารถเอาข้อมูลค่าใช้จ่ายการใช้งาน BigQuery ที่ผ่านมาในโปรเจคต์ มาเซฟกลับเข้า BigQuery เป็นตารางใหม่ เพื่อนำมาวิเคราะห์ค่าใช้จ่ายได้ครับ ผ่านทาง Billing Exports Feature โดยตารางที่ได้จะระบุข้อมูลต่างๆ เช่น วันเวลาที่ใช้ ค่าใช้จ่ายที่เกิดขึ้น รูปแบบการใช้งาน และข้อมูลอื่นๆ ให้ไว้ครับ

Billing Export: Visualization

ตัวอย่างการ Visualize ค่าใช้จ่ายผ่านDataStudio (https://cloud.google.com/billing/docs/how-to/visualize-data)

ข้อมูลดังกล่าวสามารถนำมาวิเคราะห์รูปแบบการใช้งาน และแนวโน้มการใช้งานในอนาคตได้ต่อไป เช่น ในรูปด้านบนจะเป็นการนำ Google Data Studio มาวิเคราะห์ข้อมูลจาก Google Billing สามารถอ่านเพิ่มเติมได้ที่ Google Documentation หรือจาก บทความอันนี้ครับ


Plan B: ลดจำนวน Query ที่ใช้ลง

Strategy B1 —  Caching

หนึ่งในวิธีลดจำนวนการใช้งาน คือการเซฟผลลัพธ์ของการคำนวณที่ต้องใช้บ่อยๆไว้ตั้งแต่ตอนที่คำนวณครั้งแรกสุด พอเวลาต้องการข้อมูลพวกนี้อีกครั้งก็สามารถอ้างอิงจากผลลัพธ์เก่าได้เลยโดยที่ไม่ต้องคำนวณใหม่ หรือก็คือการ Caching นั่นเอง

ซึ่งโชคดีที่ Google BigQuery มี built-in cache แถมมาให้ในตัวแล้ว ซึ่งจะถูกเปิดใช้งานให้โดยอัตโนมัติ และไม่คิดค่าใช้จ่ายเพิ่มเติมในการเรียกข้อมูลจาก Cached Results ซึ่งทำให้หากเราเรียก Query เดิมซ้ำหลายๆครั้งภายในช่วง 24 ชั่วโมง เราจะถูกเก็บเงินแค่ครั้งแรกสุดเท่านั้น

Cache จะมีให้เลือกใช้หรือปิดใช้ตอนสั่ง Query ผ่าน WebUI หรือ API ได้เลย

ยกเว้นในบางกรณีที่ built-in cache จะไม่ถูกใช้งาน เช่น

  • ผลลัพธ์ถูกบันทึกลงตารางผลลัพธ์อื่นๆ
  • มีข้อมูลบางส่วนถูกเปลี่ยนแปลง เช่นมีข้อมูลใหม่รอถูกนำเข้าอยู่ใน Streaming Buffer
  • ใน Query มีการระบุ Non-deterministic Function เช่น CURRENT_TIMESTAMP(), NOW(), CURRENT_USER() ซึ่งเป็นการอ้างถึงข้อมูล ณ ปัจจุบัน
  • Cache ถูกปิดจากผู้ใช้งานโดยผู้ใช้เอง
  • ผลลัพธ์ขนาดใหญ่เกิน 128MB

Plan C: ลดขนาดข้อมูลที่ต้องใช้ในแต่ละ Query ลง

Strategy C1 — ลดปริมาณ Column ที่ใช้

การลดจำนวนข้อมูลที่ใช้สามารถทำได้โดยการเลือกดึง Column ให้น้อยลง ซึ่งสำหรับ BigQuery ระบบจะเก็บเงินเราแค่ในส่วนของปริมาณข้อมูลใน Column ที่เราเรียกใช้ แทนที่จะเป็นปริมาณข้อมูลของทั้งตาราง (โดยดูจากชื่อ Column ที่ระบุหลัง SELECT(…) ใน SQL)

โดยขนาดของ Column นั้นสามารถประมาณได้จากขนาดของชนิดข้อมูลแต่ละประเภท (Int/Float/Bool/String/etc.) ตามตัวอย่างดังนี้

  • ยกตัวอย่างตารางที่ประกอบด้วย Column: A, B, C, D
  • สีเหลืองแทนข้อมูลส่วนที่ไม่ถูกใช้งาน
  • สีส้มแทนข้อมูลส่วนที่ถูก Query (นำไปคิดเงิน)

หากเลือกทุก Column (SELECT *) จะพบว่าข้อมูลทั้งหมดจะถูกนำไปคิดเงิน

ในขณะที่ถ้าเราเลือกแค่บาง Column จะพบว่า BigQuery จะเก็บเงินแค่จากคอลัมน์ส่วนที่เรียกใช้เท่านั้น ซึ่งในตัวอย่างคือขนาดข้อมูลทั้งหมดที่อยู่ในคอลัมน์ B และ D

เพราะงั้นในการเรียกใช้ BigQuery ควรหลีกเลี่ยงการใช้ SELECT * และเลือกใช้ข้อมูลแค่จาก Column ที่จำเป็นเท่านั้นครับ 🙂


Strategy C2 — ลดปริมาณ Row ที่ใช้ = ลดขนาดตาราง

อีกแนวทางหนึ่งในการลดประมาณข้อมูลคือการลดจำนวนแถวที่ใช้ แต่เนื่องจากข้อจำกัดของ BigQuery ที่บังคับค้นทั้งตาราง ทำให้เราต้องถอยกลับไปลดที่ขนาดตารางแทนครับ

การลดขนาดตารางสามารถทำได้โดยแบ่งตารางที่เราใช้ออกเป็นตารางเล็กๆ หลายๆ อัน แทนที่จะเป็นตารางใหญ่ตารางเดียวครับ เช่น

เรานำมาแยกเป็นตารางย่อยๆ โดยที่หนึ่งตารางเก็บข้อมูลจากใน 1 วันแทน จะได้เป็น

ในกรณีนี้ตอนที่ใช้งานจริงๆ เวลาต้องการค้นหาข้อมูลจากในช่วงไม่กี่วัน ตัว BigQuery ก็จะคำนวณค่าใช้จ่ายแค่จากตารางที่ต้องใช้งานครับ

การแบ่งตารางสามารถทำได้สองแบบหลักๆ คือ

  • Strategy C2 / Method 1  – Sharded Tables: แยกตารางเอง
  • Strategy C2 / Method 2 – Partitioned Tables: แยกตารางโดยอัตโนมัติ (BigQuery built-in)

Strategy C2 / Method 1 — Sharded Tables

เป็นการแบ่งตารางเองครับ ซึ่งแปลว่าเราต้อง

  • แยกตารางออกเป็นหลายๆ ตารางเอง
  • ในตอนเอาข้อมูลเข้า ต้องนำข้อมูลเข้าหลายๆ ตาราง แยกกันเอง
  • การ Query ต้องไปแก้ที่ส่วน Query ให้ทำการค้นจากหลายตารางรวมกันแทนที่จะค้นจากตารางเดียวครับ

เช่น จากตารางในตัวอย่างก่อนหน้า เราก็มาแบ่งเป็น

  • salesdata_dataset_1
  • salesdata_dataset_2
  • salesdata_dataset_3
  • salesdata_dataset_4

หลังจากนั้นในการ Query เราจะสามารถใช้ BigQuery Wildcard Tables และ _TABLE_SUFFIX มาทำการระบุตารางหลายๆอันพร้อมกันได้ครับ

โดย * (Wildcard) จะทำให้เราเลือกตารางหลายๆ ตารางพร้อมกันได้ และสามารถระบุเงื่อนไขสำหรับกรองตารางที่ระบุมาได้เพิ่ม ผ่านทางการใช้ _TABLE_SUFFIX ในส่วน WHERE (โดยให้คิดว่า _TABLE_SUFFIX มาแทนตำแหน่งที่ใส่ * ลงไป) เช่น

ในกรณีนี้จะให้ผลเหมือนกับการ Query จากตาราง salesdata_dataset_2, salesdata_dataset_3, และ salesdata_dataset_4 แล้วมา UNION ALL กันครับ

อย่างไรก็ตาม จุดที่ต้องคำนึงเพิ่มเติมในส่วนนี้คือ ใน 1 Query เราจะสามารถระบุตารางได้ ไม่เกิน 1000 ตารางย่อย และ Query ขนาดห้ามเกิน 256 KB ครับ จึงกลายมาเป็นข้อจำกัดไม่ให้เราแบ่ง Table ออกมามากเกินไปครับ / อ้างอิง


Strategy C2 / Method 2 — Partitioned Tables

อีกวิธีหนึ่งในการแบ่งตารางคือใช้ฟีเจอร์ Partitioned Tables ของ BigQuery เป็นตัวแบ่งตารางให้ครับ ซึ่งในวิธีนี้

  • ไม่ต้องแยกตารางเป็นหลายๆ ตารางเอง แต่ต้องตั้งค่าเพิ่มเติมตอนสร้างตารางว่าต้องการแบ่งโดยใช้เกณฑ์อะไร
  • ในตอนเอาข้อมูลเข้าก็สามารถเอาข้อมูลเข้าเหมือนใช้ตารางเดียวได้ตามปกติ
  • การ Query ต้องไปแก้ที่ส่วน Query ให้ทำการค้นจากหลายตารางรวมกันแทนที่จะค้นจากตารางเดียวครับ

ซึ่งในปัจจุบันตัวระบบสนับสนุนเกณฑ์แค่การแบ่งโดยดูจากเวลา (วันที่) เพียงอย่างเดียวครับ ในตอนสร้างตารางเราต้องระบุชื่อคอลัมน์ที่เก็บ Timestamp ของแต่ละแถวเพื่อมาใช้เป็นเกณฑ์ในการแบ่งตารางย่อยต่อไป ในการตั้งค่าสามารถทำได้หลายวิธี สามารถศึกษาเพิ่มเติมได้ที่นี่ ครับ

หลังจากนั้นในการ Query เราจะใช้ Pseudo-Column: _PARTITIONTIME / _PARTITIONDATE เป็นตัวกรองตารางย่อย ผ่านทางระบุลงไปในส่วน WHERE ดังนี้ครับ

ข้อดีของวิธีนี้คือสามารถทำได้ง่ายกว่าแบบแรกมากๆ แต่ก็ทำได้แค่การแบ่งโดยอ้างอิงจากเวลาเพียงอย่างเดียว อาจจะไม่ตอบโจทย์สำหรับการใช้งานที่เหมาะกับการแบ่งด้วยเกณฑ์อื่นๆ

จากตัวอย่างด้านล่าง ซึ่งเป็นการค้นข้อมูลอย่างเดียวกันจากตารางเดียวกัน จะเห็นว่าเมื่อเรามีการกำหนดเงื่อนไขตารางย่อยเพิ่มโดยระบุ _PARTITIONTIME ให้ค้นแค่ตารางที่เก็บข้อมูลของช่วงวันที่เราต้องการ (ในที่นี้คือ 15/5–16/6) ก็จะสามารถลดปริมาณข้อมูลที่ต้องใช้ลงมาจาก 100GB ให้เหลือแค่ 115MB ได้เลย 🙂

การค้นหาแบบไม่ได้กำหนดเงื่อนไขตารางย่อย -> 10GB
การค้นหาแบบกำหนดเงื่อนไขตารางย่อย -> 115MB

สำหรับรูปแบบการใช้งาน Partitioned Tables อื่นๆ สามารถอ่านเพิ่มเติมได้จากที่นี่ ครับ


TL;DR + Further Reading

BigQuery เป็น Data Warehouse ตัวหนึ่งที่สามารถจัดการปัญหาด้าน Hardware, Performance, Maintenance, Monitoring ให้เราได้พอสมควร สิ่งที่เราต้องทำมีแค่เอาข้อมูลเข้า เขียน SQL ไปเรียกใช้ และจ่ายเงิน ทุกปัญหาก็จะหมดไป — จะได้เอาเวลาไปทำสิ่งที่อยากทำ (นอน)

แต่เนื่องจาก BigQuery มีค่าใช้จ่ายค่อนข้างสูงหากไม่ระวังให้ดี แต่ถ้าค่าใช้จ่ายจะสูงขนาดนี้คงเอาไปใช้จริงไม่ได้แน่ๆ ซึ่งในบทความนี้เสนอวิธี Cache ผลลัพธ์, Query แค่จาก Column ที่ต้องการ หรือแยกตารางออกเป็นส่วนเล็กๆ เพื่อลดค่าใช้จ่ายลงครับ

นอกจากนี้ผู้เขียนขอแนะนำบทความเพิ่มเติมเป็นแนวทางการใช้งานตาม Best Practice ที่ Google ได้ระบุไว้ ดังนี้ครับ 🙂


บทความนี้ก็เป็นพาร์ทสุดท้ายในซีรีส์ BigQuery แล้ว ขอขอบคุณผู้อ่านทุกท่านครับ หากมีเขียนผิดพลาดหรือข้อเสนอแนะใดๆ ทักแชทมาได้ที่ Cleverse Facebook Page ได้เลยครับ /กราบ

ติดตามชมบทความต่อๆ ไปจากบล็อก Cleverse ได้ในไม่ช้า..
ขอเวลาอีกไม่นาน.. -w-

SARIN
Software Engineer.
“anything-except-frontend” software/data engineer
@ Cleverse, Thailand.

Also, machine learning enthusiasts and photographer.
Next Article
4 หลักจัด illustration อย่างไรให้ง้ามงาม
สมัครงาน