← Back to PostgreSQL course
PHASE 2: DEEP DIVE INTO THE 4 PILLARS PILLAR 4: PRE-COMPUTATION ⚡

Day 8: Pillar 4 - Pre-computation with Materialized Views & Background Scheduling Engine with pg_cron (กลไก Pre-computation ด้วย Materialized Views, การทำ Incremental/Concurrent Refresh, และการตั้งเวลาประมวลผลฉากหลังอัตโนมัติด้วย pg_cron)

ทลายคอขวด Analytical Dashboard ที่ถ่วงระบบให้พัง! เปลี่ยนจาก Read-time Computation (สแกนสด 100 ล้านแถวเมื่อมีคนเปิดดู) ไปเป็น Pre-computation (คำนวณรอล่วงหน้าบนดิสก์) ด้วย Materialized Views ปลดล็อกการอ่านข้อมูลแบบ $O(1)$ เร็วขึ้น 1,000 เท่า พร้อมกลไก REFRESH CONCURRENTLY ที่ไม่บล็อกการอ่าน และการตั้งเวลาอัปเดตอัตโนมัติใน Database Engine ด้วย pg_cron

📍 ตำแหน่งปัจจุบันของคุณบน Roadmap (18-Day Masterclass) Phase 2: Pillar 4 of 4 (จบ Phase 2 ครบทุกเสาหลัก!)
Phase 1: Architecture Synthesis (Days 1–4) ✓
➔
Day 5: Pillar 1 - UDFs & Inlining ✓
➔
Day 6: Pillar 2 - Stored Procedures ✓
➔
Day 7: Pillar 3 - Event Triggers ✓
➔
Day 8: Pillar 4 - Pre-computation & pg_cron
➔
Day 9: Vectorized & Parallel Optimization
เปิดบท

ถอดรหัสคำสำคัญของวันนี้

เสาหลักต้นที่สี่คือการเสิร์ฟรายงาน — คำนวณของยากไว้ล่วงหน้าฉากหลัง แล้วให้แดชบอร์ดอ่านผลที่พร้อมแล้ว ไม่ไปดึง CPU ของระบบซื้อขายหน้าร้าน

Pre-computation

การคำนวณผลลัพธ์ล่วงหน้าฉากหลัง เตรียมไว้ก่อนที่คนจะมาเรียกดู

Materialized Views

ตารางพิเศษที่เอาผลจาก Query ยากๆ มาเซฟค้างไว้เป็นตารางจริงบนดิสก์ พอคนมาเรียกดู อ่านจากตารางนี้ได้ทันทีในระดับมิลลิวินาที

pg_cron

ตัวตั้งเวลาที่ฝังในฐานข้อมูล คอยสั่งรันคำสั่งตามเวลา เช่น ทุก 15 นาที หรือทุกเที่ยงคืน

โดยรวมวันนี้คือการคำนวณรายงานยากๆ ล่วงหน้าแล้วเซฟลง Materialized View โดยให้ pg_cron สั่งรีเฟรชฉากหลังแบบไม่บล็อกคนใช้งาน (REFRESH CONCURRENTLY)

เปรียบกับชีวิตจริง

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

ช่วยแยกงานคำนวณรายงานหนักๆ ออกจากงานซื้อขายหน้าร้าน ทำให้แดชบอร์ดเปิดได้เร็ว โดยไม่ดึง CPU ของระบบหลัก

1

🏛️ มโนทัศน์ สถาปัตยกรรมองค์กร และสถานการณ์จริง (Concept & Architecture)

ในระบบงานระดับ Enterprise คำสั่งประเภทวิเคราะห์ข้อมูล (Analytical & Dashboard Queries) มักต้องทำ SUM, AVG, COUNT และ GROUP BY บนตารางประวัติธุรกรรมที่มีข้อมูลหลายสิบล้านถึงหลายร้อยล้านแถว หากปล่อยให้ผู้ใช้งานหรือแดชบอร์ดเรียกยิง Query เหล่านี้สดๆ บนตาราง OLTP ในช่วงเวลาที่มีปริมาณการใช้งานสูงสุด (Peak Hours) ฐานข้อมูลจะต้องสแกนดิสก์และใช้ CPU มหาศาล จนทำให้ระบบรับชำระเงินและหน้าบ้านค้างล่ม!

🚨 วิกฤตแดชบอร์ดผู้บริหาร 200 คน: ยิงสแกนตาราง 100 ล้านแถวซ้ำๆ จนระบบช้อปปิ้งพัง!

ระบบแอปพลิเคชัน E-Commerce มีผู้บริหารและผู้จัดการสาขา 200 คน เปิดดูแดชบอร์ดสรุปยอดขายแยกตามหมวดหมู่และภูมิภาค ซึ่งข้อมูลถูกดึงจากตาราง orders จำนวน 100,000,000 แถว ฝั่ง Front-End ตั้งเวลา Auto-Refresh ทุกๆ 1 นาที ทีมพัฒนาเดิมเข้าใจผิดจึงสร้าง Standard View (CREATE VIEW) ห่อคำสั่ง SQL ไว้:

45 วินาที/หน้า
แดชบอร์ดหมุนค้างเกิน SLA สแกนดิสก์หนักหน่วง
100% CPU
DB Engine รับ Query Aggregation 200 ตัวพร้อมกัน
30% Timeout
ลูกค้าหน้าบ้านกด Checkout ไม่ผ่านเพราะดิสก์ติดคอขวด

ต้นตอของวิกฤตนี้คือ Standard View เป็นเพียงคำสั่งตรรกะ (Stored Query) ไม่ได้บันทึกผลลัพธ์เก็บไว้ เมื่อคน 200 คนกดเปิด แดชบอร์ดจะบังคับให้ฐานข้อมูลสแกน 100 ล้านแถวซ้ำใหม่ 200 รอบ! ทางออกเดียวคือการเปลี่ยนมาใช้ Pillar 4 Pre-computation Architecture บันทึกผลลัพธ์ลงดิสก์ล่วงหน้าครับ!

🍲 อุปมาอุปไมย: ร้านอาหารตามสั่งทำสดทีละจาน vs ร้านข้าวแกงตักเสิร์ฟใน 2 วินาที

❌ Read-time Computation (ร้านตามสั่งเคี่ยวน้ำซุป 3 ชั่วโมงสดๆ ต่อลูกค้า 1 คน)

เปรียบเหมือนมีลูกค้าเดินเข้ามาสั่งต้มเนื้อ 200 คน แล้วพ่อครัวต้องเริ่มจุดไฟ ต้มน้ำ และเคี่ยวกระดูกเนื้อสดๆ ตั้งแต่เริ่มต้นให้ลูกค้าแต่ละคน (เหมือน Standard View ที่สแกน 100 ล้านแถวใหม่ทุกครั้ง)

  • ลูกค้าคนแรกยืนรอ 45 นาที ลูกค้าคนที่ 200 ต่อคิวล้นออกนอกถนน
  • เตาแก๊สทำงานเต็ม 100% จนหม้อไหม้ (CPU & Disk I/O Exhaustion)
  • ลูกค้าที่แค่จะมาซื้อน้ำเปล่าหน้าเคาน์เตอร์ (OLTP Checkout) จ่ายเงินไม่ได้จนต้องเดินหนี!
✅ Pre-computation (ร้านข้าวแกงต้มหม้อใหญ่ไว้ล่วงหน้า แล้วตักราดข้าวทันที)

พ่อครัวเคี่ยวน้ำซุปหม้อใหญ่ไว้ในครัวฉากหลังตั้งแต่ตี 5 พอเปิดร้าน ลูกค้า 200 คนเดินเข้ามา พ่อครัวแค่ตักใส่ถ้วยเสิร์ฟในเวลา 0.002 วินาที (ระดับมิลลิวินาที)

  • เปลี่ยนเวลาค้นหาจากคำนวณ $O(N)$ 100 ล้านแถว เหลือเพียง $O(1)$ อ่านผลสรุป 100 แถวจากดิสก์ทันที
  • ขณะที่พ่อครัวฉากหลังเติมน้ำซุปใหม่ (REFRESH CONCURRENTLY) ลูกค้าข้างหน้ายังตักกินได้ต่อเนื่อง ไม่ติดบล็อก!
  • ลูกค้าหน้าบ้านซื้อสินค้าได้ราบรื่น 100% เพราะไม่มี Query หนักๆ มาแย่งทรัพยากร

⚖️ การเปรียบเทียบเชิงสถาปัตยกรรม: Standard View vs. Materialized View ใน PostgreSQL

มิติเปรียบเทียบสถาปัตยกรรม Standard View (CREATE VIEW) Materialized View (CREATE MATERIALIZED VIEW)
การจัดเก็บข้อมูลทางกายภาพ (Storage) ❌ ไม่มีข้อมูลบนดิสก์ (เป็นเพียง Stored Query Text) ✅ บันทึกตารางผลลัพธ์จริงลงดิสก์ (มี Heap Storage เสมือนตารางจริง)
ภาระการคำนวณ (Compute Timing) คำนวณสดทุกครั้งที่มีการ SELECT (Read-time Computation) คำนวณล่วงหน้าตอนสั่งสร้าง/รีเฟรช (Pre-computation)
ความสามารถในการสร้าง INDEX ❌ สร้าง Index ไม่ได้ (เพราะไม่มีโครงสร้างตารางจริง) ✅ สร้าง Index ได้เหมือนตารางจริงทุกประการ (B-Tree, GIN, Hash)
ความสดใหม่ของข้อมูล (Data Freshness) Real-time 100% เสมอตามตารางหลัก Eventually Consistent (อัปเดตตามรอบที่สั่ง REFRESH)
ความเร็วในการตอบสนอง (Query Latency) ช้ามากหากข้อมูลหลักมีขนาดใหญ่ ($O(N)$ Disk Scan) เร็วระดับมิลลิวินาที ($O(1)$ อ่านผลลัพธ์ที่คำนวณไว้แล้ว)
ผลกระทบต่อระบบ OLTP หน้าบ้าน แย่ง CPU และ Buffer Cache สูงมากในเวลา Peak แทบเป็นศูนย์ (ย้ายภาระไปประมวลผลฉากหลังด้วย pg_cron)
สถาปัตยกรรมระดับลึก: การเปรียบเทียบ Read-time vs Pre-computation Pipeline พร้อมกลไก REFRESH CONCURRENTLY Pillar 4 Pre-computation Pipeline
❌ แย่: Standard View / Read-time Computation (สแกนสด 100M แถว) ✅ ปัง: Materialized View + pg_cron + Non-blocking Refresh 1. Dashboard User 200 คน ส่ง Query พร้อมกัน • SELECT * FROM v_sales_report_flawed; (Standard View) • View ไม่มีข้อมูลจริง: Planner ต้องขยาย Query ไปแตะตาราง orders ⚠️ บังคับทำ Full Table Scan 100,000,000 แถว × 200 รอบ! 2. วิกฤต Compute & Disk I/O Churn • เผาผลาญ CPU Cores คำนวณ SUM/AVG/COUNT ซ้ำซาก • Data Pages 8KB ถูกกวาดล้างออกจาก shared_buffers (Cache Thrashing) • ลูกค้าหน้าบ้านกดซื้อของเจอ Disk I/O Wait ติดคอขวด 💥 Checkout Transactions ล่มสลายไปมากกว่า 30%! ผลกระทบต่อธุรกิจ: Dashboard ล่ม & ลูกค้าหนี • ผู้บริหารรอผลหน้าจอหมุนค้างนานกว่า 45 วินาที • เซิร์ฟเวอร์ร้อนจัด CPU แตะ 100% ตลอดเวลาในเวลา Peak สูญเสียรายได้หลักล้านบาท และผิด SLA ข้อตกลงระดับบริการ 1. Dashboard Client Query (Pre-computed Read) • SELECT * FROM mv_sales_report_production WHERE region_id = 5; ⚡ อ่านตรงจากผลลัพธ์บนดิสก์ที่คำนวณไว้แล้ว (100 แถว ไม่ใช่ 100M!) • วิ่งผ่าน UNIQUE INDEX idx_mv_sales_rep_pk ได้ผลลัพธ์ใน 2-4 ms • CPU ทำงานแทบเป็น 0% หน้าจอโหลดเร็วทันใจ 1,000 เท่า! 2. Background Automation Engine (pg_cron + Non-blocking Refresh) • pg_cron สั่งรันคำสั่งฉากหลังอัตโนมัติตามตารางเวลา (เช่น ทุก 15 นาที) REFRESH MATERIALIZED VIEW CONCURRENTLY ... สร้าง Snapshot ใหม่ฉากหลังแล้วสลับ Diff / Merge ผู้ใช้ยัง SELECT ได้ตลอดเวลา! • ไม่พึ่งพา External OS Cron, ควบคุมได้จบใน Database Engine 100% เวลารวม: จาก 45 วินาที เหลือเพียง 4 มิลลิวินาที (เร็วขึ้น 1,000x!) CPU Load บนตารางหลักลดเหลือ 0%, ระบบซื้อขายหน้าบ้านทำงานได้เต็ม 100%
🎙️ สคริปต์คำพูดสำหรับพรีเซนท์บนเวที (Presentation Pitch Script)

"ทุกท่านครับ การเปิดแดชบอร์ดแล้วระบบล่ม ไม่ได้แปลว่าฐานข้อมูลเราประมวลผลไม่ได้ แต่เกิดจากการที่เราฝืนสั่งให้ระบบสแกนตาราง 100 ล้านแถวใหม่ทุกๆ 1 นาทีโดยไม่จำเป็น!

ด้วย Pillar 4 Architecture เราจะเปลี่ยนจากการคำนวณสด มาใช้ Materialized Views บันทึกผลสรุปไว้ล่วงหน้า ร่วมกับการทำ REFRESH CONCURRENTLY ผ่าน pg_cron ในระดับ Database Engine ผลลัพธ์คือแดชบอร์ดเปิดได้เร็วขึ้น 1,000 เท่า จาก 45 วินาที เหลือเพียง 4 มิลลิวินาที และตัด CPU Load บนตารางหลักเหลือเกือบ 0% โดยไม่กระทบต่อการซื้อขายหน้าบ้านแม้แต่มิลลิวินาทีเดียวครับ"

🧮 วิดเจ็ตทดลอง: ตัวจำลองผลลัพธ์ Pre-computation (Analytical Latency Simulator)

ลองปรับจำนวนแถวในตาราง OLTP (Total Rows) และจำนวนผู้บริหารที่เปิดดูแดชบอร์ดพร้อมกัน เพื่อเปรียบเทียบเวลาโหลดระหว่าง Standard View (สแกนสด $O(N)$) กับ Materialized View ($O(1)$ Pre-computed)

ผลลัพธ์เปรียบเทียบเวลาประมวลผล (Dashboard Response Time):
• Standard View (คำนวณสด): ~45.0 วินาทีต่อหน้า (CPU 100% เสี่ยงล่ม)
• Materialized View (Pre-computed): 0.004 วินาที (4 ms) ผ่าน Index บนผลลัพธ์ล่วงหน้า
เร็วขึ้น 11,250 เท่าตัว!
2

💻 ปูพื้นฐานไวยากรณ์ & แบบฝึกหัดไต่ระดับ (Pre-computation & pg_cron Syntax)

การสร้างระบบ Pre-computation ใน PostgreSQL ต้องเริ่มตั้งแต่การใช้คำสั่ง CREATE MATERIALIZED VIEW, การสร้าง UNIQUE INDEX เพื่อเปิดทางให้ทำ Concurrent Refresh, และการผูกเข้ากับ pg_cron สั่งงานอัตโนมัติ:

🧱 แกะโครงสร้างไวยากรณ์ 4 สเต็ป: แม่แบบสถาปัตยกรรม Pre-computation & pg_cron

ไวยากรณ์หลัก: High-Performance Pre-computation Blueprint Pillar 4 Architecture
-- [สเต็ปที่ 1: สร้าง Materialized View บันทึกผลลัพธ์ลงดิสก์]
CREATE MATERIALIZED VIEW mv_daily_sales_summary AS
SELECT
    order_date,
    category_id,
    COUNT(order_id)   AS total_orders,
    SUM(total_amount) AS total_revenue
FROM orders
GROUP BY order_date, category_id
WITH DATA; -- 🎯 [1] คำนวณผลลัพธ์และเซฟลง Data Pages บนดิสก์ทันที

-- [สเต็ปที่ 2: สร้าง Unique Index จำเป็นสำหรับการทำ REFRESH CONCURRENTLY]
CREATE UNIQUE INDEX idx_mv_daily_sales_key
ON mv_daily_sales_summary (order_date, category_id); -- 🎯 [2] ต้องมี Unique Key สำหรับ Merge ข้อมูล

-- [สเต็ปที่ 3: สั่งรีเฟรชแบบ Non-blocking (อ่านข้อมูลได้ตลอดเวลาขณะรีเฟรช)]
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_sales_summary; -- 🎯 [3] ไม่ล็อกตาราง SELECT อ่านได้ตลอด

-- [สเต็ปที่ 4: ตั้งเวลาทำงานอัตโนมัติด้วย pg_cron (เช่น รันทุก 15 นาที)]
SELECT cron.schedule(
    'refresh_daily_sales_job',                           -- [4.1] ชื่อ Job ในระบบ
    '*/15 * * * *',                                      -- [4.2] Cron Expression (ทุก 15 นาที)
    'REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_sales_summary' -- [4.3] คำสั่ง SQL ที่จะรัน
);
💡 กฎเหล็กสำคัญ: หากไม่มี UNIQUE INDEX คำสั่ง REFRESH MATERIALIZED VIEW CONCURRENTLY จะฟ้อง Error ทันที เนื่องจาก PostgreSQL ต้องใช้ Index นี้ในการทำ Diff และสลับข้อมูลโดยไม่ต้องวาง Exclusive Lock ล็อกตาราง

🏋️‍♂️ แบบฝึกหัดไต่ระดับการเขียนจริง (จากระดับเริ่มต้น ➔ Pre-computation Engine ระดับ Production)

🟢 Level 1: การสร้าง Materialized View และการสั่ง Refresh แบบธรรมดา ระดับเริ่มต้น
-- [1] สร้าง Materialized View สำหรับสรุปยอดคงเหลือสินค้ารายคลัง
CREATE MATERIALIZED VIEW mv_warehouse_inventory_summary AS
SELECT
    warehouse_id,
    COUNT(product_id) AS total_products,
    SUM(quantity)     AS total_stock_quantity
FROM inventory
GROUP BY warehouse_id
WITH DATA;

-- 📤 [2] เรียกดูข้อมูล (เร็วเท่ากับการ SELECT ตารางปกติ เพราะอ่านจากดิสก์ที่คำนวณไว้แล้ว)
SELECT * FROM mv_warehouse_inventory_summary WHERE warehouse_id = 10;

-- 🔄 [3] สั่งรีเฟรชข้อมูลแบบธรรมดา
-- ⚠ หมายเหตุ: คำสั่งนี้จะวาง Exclusive Lock บน MV ทำให้ผู้ใช้คนอื่น SELECT อ่านไม่ได้ชั่วคราวขณะรีเฟรช
REFRESH MATERIALIZED VIEW mv_warehouse_inventory_summary;
จุดที่ต้องสังเกต: การสั่ง REFRESH แบบธรรมดาจะเหมาะเฉพาะช่วง Maintenance Window นอกเวลาทำการ เพราะมันจะบล็อกคำสั่งอ่านข้อมูลจนกว่าจะรีเฟรชเสร็จ
🟡 Level 2: การสร้าง Unique Index เพื่อเปิดใช้งาน Non-blocking CONCURRENTLY Refresh ระดับปานกลาง
-- [1] สร้าง Unique Index บนคอลัมน์ที่เป็น Key หลักของ Materialized View
CREATE UNIQUE INDEX idx_mv_wh_inv_pk
ON mv_warehouse_inventory_summary (warehouse_id);

-- 🚀 [2] สั่งรีเฟรชแบบ CONCURRENTLY (Non-blocking)
-- ผลลัพธ์: ผู้ใช้งานยังคง SELECT อ่านข้อมูลจาก MV ได้อย่างราบรื่นขณะที่ระบบกำลังประมวลผลอัปเดตข้อมูลฉากหลัง!
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_warehouse_inventory_summary;

-- 💡 ตรวจสอบขนาดพื้นที่ของ Materialized View บนดิสก์:
SELECT pg_size_pretty(pg_total_relation_size('mv_warehouse_inventory_summary'));
จุดที่ต้องสังเกต: เมื่อมี Unique Index แล้ว เราสามารถสั่งรีเฟรชตอนกลางวันแสกๆ ได้อย่างปลอดภัย โดยไม่กระทบต่อผู้ใช้งานที่กำลังอ่านแดชบอร์ดอยู่เลย

🔴 Level 3: Refactoring โค้ด Dashboard Analytics ระดับ Production (Pre-computation Engine + pg_cron)

เปรียบเทียบโค้ดเดิมที่เป็น Standard View ที่บังคับสแกนสด 100 ล้านแถวในทุก Query กับโค้ดใหม่ที่เป็น Materialized View พร้อม Stored Procedure และการตั้งเวลาด้วย pg_cron:

❌ โค้ดเดิมแบบ Flawed: Standard View สแกนสด 100 ล้านแถว CPU 100% & โหลดนาน 45 วินาที
-- ❌ Standard View ไม่ได้บันทึกข้อมูลลงดิสก์
-- เมื่อผู้ใช้เปิดดู จะวิ่งไปสแกน 100,000,000 แถวใหม่ทุกรอบ!
CREATE OR REPLACE VIEW v_sales_report_flawed AS
SELECT
    DATE(created_at) AS sale_date,
    region_id,
    SUM(amount)      AS total_sales,
    AVG(amount)      AS avg_order_value
FROM orders
GROUP BY DATE(created_at), region_id;

-- 🚨 เมื่อคน 200 คนยิง Query พร้อมกัน:
-- SELECT * FROM v_sales_report_flawed;
-- ระบบจะพังทลายจาก Disk I/O และ CPU 100% ทันที!
วิเคราะห์ข้อเสีย: Standard View เป็นเพียง Text คำสั่ง SQL ไม่ได้ช่วยแคชข้อมูลใดๆ ทำให้ฐานข้อมูลทำงานหนักซ้ำซากโดยไม่จำเป็น
✅ โค้ดใหม่ระดับ Production: Materialized View + pg_cron + Non-blocking ตอบสนองใน 4 ms (เร็วขึ้น 1,000x)
-- [Statement 1] สร้าง Materialized View สรุปข้อมูลลงดิสก์ล่วงหน้า
CREATE MATERIALIZED VIEW mv_sales_report_production AS
SELECT
    DATE(created_at) AS sale_date,
    region_id,
    COUNT(id)        AS total_orders,
    SUM(amount)      AS total_sales,
    AVG(amount)      AS avg_order_value
FROM orders
GROUP BY DATE(created_at), region_id
WITH DATA;

-- [Statement 2] สร้าง UNIQUE INDEX เพื่อรองรับ CONCURRENTLY Refresh
CREATE UNIQUE INDEX idx_mv_sales_rep_pk
ON mv_sales_report_production (sale_date, region_id);

-- [Statement 3] สร้าง Stored Procedure สำหรับห่อหุ้มตรรกะการรีเฟรชและทำ Logging
CREATE OR REPLACE PROCEDURE pr_refresh_sales_report_mv()
LANGUAGE plpgsql
AS $$
DECLARE
    v_start_time TIMESTAMPTZ := CURRENT_TIMESTAMP;
BEGIN
    RAISE NOTICE 'เริ่มกระบวนการ REFRESH MATERIALIZED VIEW CONCURRENTLY...';

    -- 🎯 สั่งรีเฟรชแบบไม่บล็อกการอ่านของผู้ใช้
    REFRESH MATERIALIZED VIEW CONCURRENTLY mv_sales_report_production;

    RAISE NOTICE 'รีเฟรช MV สำเร็จในเวลา %', CURRENT_TIMESTAMP - v_start_time;
END $$;

-- [Statement 4] สั่งตั้งเวลาการประมวลผลฉากหลังอัตโนมัติด้วย pg_cron (รันทุกๆ 30 นาที)
SELECT cron.schedule(
    'cron_refresh_sales_mv_job',                  -- ชื่อ Job ในระบบ
    '*/30 * * * *',                               -- Cron Schedule (ทุก 30 นาที)
    'CALL pr_refresh_sales_report_mv()'           -- เรียกใช้งาน Procedure สั่งรีเฟรช
);
วิเคราะห์ข้อได้เปรียบ: ผลการคำนวณถูกบันทึกรอไว้ล่วงหน้า แดชบอร์ดโหลดเร็วระดับมิลลิวินาที, การรีเฟรชทำฉากหลังแบบ Non-blocking และมี `pg_cron` ดูแลระบบอัตโนมัติ 100% ภายในฐานข้อมูล
3

📝 คลังข้อสอบและแบบประเมินความรู้ (18 ข้อ Multiple Choices พร้อมเฉลยยิบ)

แบบทดสอบวัดระดับความเข้าใจ Pillar 4: Pre-computation with Materialized Views & Background Scheduling with pg_cron (Standard vs Materialized View, REFRESH CONCURRENTLY, UNIQUE INDEX, cron.schedule) และข้อสอบสะสมทบทวนครบทั้ง Day 1–7 คลิกเลือกคำตอบ ก, ข, ค, หรือ ง เพื่อดูผลลัพธ์และคำอธิบายอย่างละเอียดทันที

📊 สรุปผลการประเมิน Pillar 4: Pre-computation (Day 8) 0 / 18
ความคืบหน้า ตอบแล้ว 0 จาก 18 ข้อ

🎯 สรุปหมุดเชื่อมโยง & ก้าวต่อไปสู่ Day 9

บทเรียน Day 8: Pillar 4 - Pre-computation with Materialized Views & Background Scheduling Engine with pg_cron แสดงให้เห็นถึงเทคนิคการยกเลิกภาระการคำนวณสถิติหนักๆ บนตาราง OLTP โดยการเปลี่ยนมาทำ Pre-computation บันทึกผลลัพธ์ลงดิสก์ด้วย Materialized Views พร้อมใช้ REFRESH CONCURRENTLY ร่วมกับ pg_cron เพื่ออัปเดตข้อมูลฉากหลังอัตโนมัติโดยไม่กระทบต่อผู้ใช้งานหน้าบ้าน

🚩 ก้าวต่อไปสู่ Day 9:

Vectorized Processing, Set-Based Logic & Parallel Query Optimization: ในวันถัดไป เราจะไปเจาะลึกการเพิ่มประสิทธิภาพระดับขีดสุด โดยเปลี่ยนการเขียนโค้ดแบบวนลูปทีละแถว (Procedural RBAR - Row-By-Agonizing-Row) มาเป็นการประมวลผลแบบเวกเตอร์กลุ่มข้อมูล (Set-Based Vectorized Processing) และการเปิดใช้งาน Parallel Query Execution เพื่อดึงพลังของ Multi-core CPU มาประมวลผลข้อมูลขนาดใหญ่ครับ!