PipeCraft

Roadmap Progress

ข้อมูลเบื้องต้นเกี่ยวกับวิศวกรรมข้อมูล (Introduction to Data Engineering) Python สำหรับ Data Engineering พื้นฐาน Linux & CLI สำหรับวิศวกรข้อมูล Git สำหรับระบบงานข้อมูลและทีมพัฒนา พื้นฐานเครือข่าย เว็บเทคโนโลยี และระบบกระจายศูนย์ (Web Fundamentals, Networking & Distributed Systems) SQL ขั้นสูง (Window Functions & Optimization) ฐานข้อมูลไม่ใช่เชิงสัมพันธ์ (NoSQL Databases & Modern Stores) การออกแบบโครงสร้างข้อมูล (Star/Snowflake & SCD) โครงสร้างพื้นฐานเครือข่ายระบบคลาวด์ (Cloud-based Networking) สถาปัตยกรรม Data Lakehouse (Apache Iceberg & MinIO) Local-first Data Engineering ด้วย DuckDB โครงสร้างพื้นฐานในรูปแบบโค้ด (IaC ด้วย Terraform) การแปลงข้อมูลระดับโปรด้วย dbt-core ข้อตกลงร่วมด้านข้อมูล (Data Contracts) การบริการและการส่งต่อข้อมูลวิเคราะห์ (Data Serving & Reverse ETL) การประมวลผลข้อมูลขนาดใหญ่แบบกระจายด้วย Apache Spark ระบบจัดการเวิร์กโฟลว์ข้อมูล (Airflow, Dagster & Prefect) การประมวลผลข้อมูลแบบเรียลไทม์ด้วย Kafka & Redpanda การจัดการคอนเทนเนอร์และคลัสเตอร์ (Containers & Kubernetes) ระบบ CI/CD และการเฝ้าระวังคุณภาพข้อมูล (CI/CD, Monitoring & Testing) ระบบความปลอดภัยและการควบคุมข้อมูล (Security, Governance & Privacy) ระบบปฏิบัติการและประมวลผลโมเดล (Machine Learning & MLOps) รากฐานของ AWS VPC การจัดการเส้นทางขั้นสูงและ NAT Gateway การเชื่อมต่อหลาย VPC และ Hybrid Cloud VPC Endpoints (PrivateLink) ระบบรักษาความปลอดภัยขอบเขตเครือข่าย สถาปัตยกรรมเครือข่ายสำหรับ EKS IPv6 และการจัดการ IP Address สถาปัตยกรรมเครือข่ายระดับโลก แก่นแท้ของสถาปัตยกรรม Kubernetes สถาปัตยกรรมเครื่องและคอมโพเนนต์ เลเยอร์ที่เชื่อมต่อได้ (Pluggable Layers) การรันบนโปรดักชันระดับองค์กร Apache Flink Stateful Stream Processing Real-Time CDC & Event Sourcing at Scale Low-Latency Stream-Table Joins & Windowing Data Lineage & Metadata Graph Engineering Statistical Anomaly Detection & Data Drift Data Incident Management & Automated DLQ Remediation Cloud Data FinOps & Cost Optimization Mechanics Data Mesh & Multi-Tenant Platform Architecture Vector Databases & AI-Ready Data Infrastructure API Fundamentals, Architectures & Core Components API Versioning, Docs, Real-Time & Microservices Production Reliability, Security & Resiliency World-Class Master Architecture & Traffic Management
บทที่ 2: การจัดเก็บและสร้างแบบจำลองข้อมูล (Data Storage & Modeling)

การออกแบบโครงสร้างข้อมูล (Star/Snowflake & SCD)

2.3 การออกแบบจำลองตารางข้อมูลและการจัดการประวัติ (Data Modeling & Historical Retention)

การออกแบบโมเดลข้อมูล (Data Modeling) คือฐานรากที่ตัดสินว่าระบบ Data Warehouse จะโตต่อไปได้อย่างมั่นคงหรือไม่ บทนี้เจาะลึกการสร้าง Star Schema, Snowflake Schema, และการทำ Slowly Changing Dimensions (SCD Type 2) ในองค์กรใหญ่

Technical Architecture Diagram

Architecture Diagram
Click to zoom
Step-by-Step Breakdown: (1) Data Source Ingestion -> (2) Processing Engine -> (3) Storage Layer -> (4) Serving API

1. เทคนิค Slowly Changing Dimension (SCD Type 0 ถึง 4)

Learning Progression

  • [BASIC] ปูพื้นฐานภาษาเข้าใจง่าย - เข้าใจคอนเซปต์ภาพรวมและการแก้ปัญหาเบื้องต้น
  • [INTERMEDIATE] โค้ด/คอนฟิกไวยากรณ์จริง - การเขียนโค้ดเพื่อใช้งานจริงในระบบ
  • [PROFESSIONAL] Under-the-hood & Performance/FinOps - กลไกเบื้องลึกและการรีดประสิทธิภาพ

Real-World Enterprise Scenario

เคสระบบการเงิน/Big Tech: การรองรับ Transaction จำนวนมหาศาลต่อวินาทีพร้อมประกัน Data Integrity สูงสุด โดยใช้สถาปัตยกรรมที่ยืดหยุ่นและการมอนิเตอร์ระดับสูง

ทฤษฎีและกลไกการทำงาน (How it works): Slowly Changing Dimensions (SCD) คือสัญญารูปแบบการบันทึกเมื่อค่ามิติธุรกิจมีการเปลี่ยนรูป: - **SCD Type 0**: สภาพคงเดิมถาวร ไม่ยอมรับการแก้ไขใดๆ เช่น วันเกิดลูกค้า - **SCD Type 1**: เขียนแก้ไขทับฟิลด์เดิมทันทีโดยไม่บันทึกประวัติเก่า (ไม่มีประวัติย้อนหลัง) - **SCD Type 2**: วิธีการมาตรฐานระดับองค์กร โดยสร้างแถวใหม่ขึ้นมาบันทึกประวัติการแก้ไข และคุมช่วงเวลาใช้งานจริงด้วยคอลัมน์ `valid_from`, `valid_to` และแฟล็กบอกความใหม่ `is_current` - **SCD Type 3**: เพิ่มคอลัมน์ใหม่คู่ขนาน (เช่น `current_city` และ `previous_city`) บันทึกการย้อนอัปเดตย้อนหลังได้เพียง 1 ขั้น - **SCD Type 4**: สร้างตารางประวัติประวัติต่างหากแยกจากตารางมิติหลัก (History Table) เพื่อป้องกันขนาดตารางหลักบวมโต

-- SQL simulation of SCD Type 2 historic row creation
-- 1. Expire current address record row
UPDATE dim_customers 
SET valid_to = CURRENT_DATE, is_current = FALSE 
WHERE customer_key = 101 AND is_current = TRUE;

-- 2. Insert new record row with new address values
INSERT INTO dim_customers (customer_key, name, city, valid_from, valid_to, is_current)
VALUES (101, 'Chawin', 'Bangkok', CURRENT_DATE, '9999-12-31', TRUE);
                    

Use Case ในชีวิตจริง (Real-world Scenario): เมื่อลูกค้าเปลี่ยนที่อยู่อาศัยในการจัดส่งสินค้า การใช้ SCD Type 2 ทำให้เมื่อวิเคราะห์ข้อมูลการขายย้อนหลังของเดือนก่อน ยอดซื้อขายจะถูกจัดประเภทอยู่ในจังหวัดเก่าซึ่งเป็นที่อยู่จริงขณะเกิดรายการได้อย่างถูกต้อง

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ตารางมิติแบบ SCD Type 2 จะเพิ่มจำนวนแถวในฐานข้อมูลอย่างมากตามจำนวนรอบการแก้ไข ส่งผลให้คำสั่ง `JOIN` ทำงานช้าลง แก้ไขโดยใช้ดัชนีคุมบนฟิลด์ `is_current` หรือทำพาร์ทิชันเน้นข้อมูลยุคปัจจุบันออกจากประวัติอดีต

2. การออกแบบสกีมาแบบ Kimball: Star Schema และ Snowflake Schema

ทฤษฎีและกลไกการทำงาน (How it works): สถาปัตยกรรมคลังข้อมูลเชิงมิติ (Dimensional Modeling) นำเสนอโครงสร้างการจัดกลุ่มข้อมูลออกเป็น 2 บทบาท: - **Fact Tables**: ตารางเก็บค่าตัวเลขที่เกิดขึ้นจากการทำธุรกรรม (เช่น ยอดเงิน, จำนวนชิ้น) มีคีย์หลักเชื่อมไปยังตารางแวดล้อม - **Dimension Tables**: ตารางเก็บคำอธิบายบริบทแวดล้อม (เช่น รายละเอียดลูกค้า, ข้อมูลสินค้า) รูปแบบการจัดแบ่งมี 2 แบบ: - **Star Schema**: ตารางมิติถูกจัดรูปแบบขยาย (Denormalized) ให้แบนราบในตารางเดียว ไม่มีการเชื่อม `JOIN` ซ้อน ช่วยให้อ่านคิวรี่เร็วสุด - **Snowflake Schema**: ตารางมิติถูกแตกรองรับมาตรฐานสกีมาแบบบรรทัดฐาน (Normalized) เพื่อประหยัดพื้นที่จัดเก็บข้อมูล แต่แลกมาด้วยความเร็วคิวรี่ที่ช้าลงจากจ๊อยน์ที่ซับซ้อน

-- Star Schema Query Layout (Simplistic and optimized for analytical scanning)
SELECT d.city, SUM(f.sales_amount) as total_sales
FROM fact_sales f
JOIN dim_customers d ON f.customer_key = d.customer_key
GROUP BY d.city;
                    

Use Case ในชีวิตจริง (Real-world Scenario): คลังข้อมูลธุรกิจค้าปลีกออกแบบด้วย Star Schema เพื่อสนับสนุนให้โปรแกรมแดชบอร์ด BI สามารถดึงสรุปประมวลผลยอดขายแยกตามเขตและประเภทสินค้าล้านระเบียนมาแสดงผลได้แบบตอบสนองรวดเร็วทันใจผู้บริหาร

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ใน Star Schema ตารางมิติจะมีข้อมูลที่ซ้ำซ้อนกันจำนวนมาก (เช่น ชื่อจังหวัดซ้ำหลายหมื่นแถว) แก้ไขโดยยอมเสียพื้นที่จัดเก็บ (ซึ่งในปัจจุบันราคา Object Storage ต่ำมาก) แลกคืนมาด้วยความคุ้มค่าของการไม่ต้องรันคำสั่ง Join ขนาดใหญ่ให้เปลืองซีพียูประมวลผล

3. สถาปัตยกรรมข้อมูลขั้นสูง Data Vault 2.0 (Hubs, Links, Satellites)

ทฤษฎีและกลไกการทำงาน (How it works): **Data Vault 2.0** ออกแบบมาเพื่อคลังข้อมูลระดับยักษ์ (Enterprise Scale) ที่ต้องป้อนข้อมูลเข้าขนานกันจากหลากหลายระบบ โดยมีโครงสร้างแยกออบเจกต์เป็น 3 ประเภทหลัก: - **Hubs**: เก็บเฉพาะคีย์รหัสธุรกิจหลัก (Business Keys) และคีย์แฮชระบุตัวตน ปราศจากรายละเอียดบริบท - **Links**: เก็บความสัมพันธ์และการทำจ๊อยน์เชื่อมโยงระหว่าง Hubs ด้วยค่าแฮช - **Satellites**: เก็บรายละเอียดและประวัติความเปลี่ยนแปลงของ Hub หรือ Link นั้นๆ พร้อมวันเวลาบันทึก สถาปัตยกรรมนี้รองรับการเขียนข้อมูลขนานกันได้เต็มสเกลเพราะไม่มีการล็อกตารางหรือเช็คเงื่อนไขความสัมพันธ์ต่างตาราง (Foreign Keys) ระหว่างนำเข้าข้อมูล

-- Data Vault Hub and Satellite schema design templates
CREATE TABLE hub_customers (
    customer_hash_key CHAR(32) PRIMARY KEY, -- MD5/SHA-256 of customer_id
    customer_id VARCHAR(50) NOT NULL,
    load_timestamp TIMESTAMP NOT NULL,
    record_source VARCHAR(50) NOT NULL
);

CREATE TABLE sat_customer_details (
    customer_hash_key CHAR(32) REFERENCES hub_customers(customer_hash_key),
    hash_diff CHAR(32) NOT NULL, -- Used to quickly detect if attributes changed
    email VARCHAR(100),
    phone VARCHAR(20),
    load_timestamp TIMESTAMP NOT NULL,
    record_source VARCHAR(50) NOT NULL,
    PRIMARY KEY (customer_hash_key, load_timestamp)
);
                    

Use Case ในชีวิตจริง (Real-world Scenario): บริษัทประกันภัยขนาดใหญ่ที่มีระบบไอทีและฐานข้อมูลลูกค้าแยกย่อย 10 ระบบ ดึงข้อมูลเข้ามารวมกันใน Data Vault โดยเชื่อมโยงผ่านเลขบัตรประชาชนเป็น Hub และให้รายละเอียดที่ต่างกันของแต่ละฐานข้อมูลแยกเก็บเป็น Satellites อิสระ

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การคิวรี่หาข้อมูลปัจจุบันจาก Data Vault มีความยุ่งยากสูงมากเพราะต้องรันคำสั่ง Join ข้อมูลข้าม Hub และ Satellite หลายสิบตาราง แก้ไขโดยสร้างตารางสรุปผลกลาง **Information Mart** ที่แปลงรูปแบบ Data Vault ให้กลายเป็นตารางมิติ Star Schema สำหรับเสิร์ฟผู้ใช้งานปลายทาง

4. การออกแบบสกีมาแบบหนึ่งต่อกลุ่ม (One-to-Many) และกลุ่มต่อกลุ่ม (Many-to-Many)

ทฤษฎีและกลไกการทำงาน (How it works): การวางความสัมพันธ์ฐานข้อมูลเชิงสัมพันธ์ต้องควบคุมตามหลักการออกแบบ: - **One-to-Many (1:N)**: วางคีย์หลักของตารางแม่ (เช่น `customer_id`) ไปเป็นคีย์นอก (Foreign Key) ในตารางลูก (เช่น `orders`) คอนฟิกเพื่อคุมความถูกต้องข้อมูลเชิงโครงสร้าง - **Many-to-Many (N:M)**: ต้องแก้ไขโดยสร้างตารางทางผ่านตรงกลางเรียกว่า **Junction Table** (หรือ Bridge Table) เพื่อเก็บคู่ความสัมพันธ์ของคีย์จากสองตารางหลัก เพื่อป้องกันตารางข้อมูลบวมและขัดต่อหลักการ Normalization

-- Junction Table implementing Many-to-Many relationship with composite primary keys
CREATE TABLE orders_products (
    order_id UUID REFERENCES orders(order_id),
    product_id UUID REFERENCES products(product_id),
    quantity INTEGER NOT NULL CHECK (quantity > 0),
    PRIMARY KEY (order_id, product_id)
);
-- Compose index on the reverse lookup column to speed up queries
CREATE INDEX idx_products_orders ON orders_products(product_id);
                    

Use Case ในชีวิตจริง (Real-world Scenario): ในฐานข้อมูลการศึกษา คลาสเรียนหนึ่งคลาสมีนักเรียนลงเรียนได้หลายคน และนักเรียนหนึ่งคนก็สามารถลงเรียนได้หลายคลาสเรียน ระบบจึงใช้ตารางทางผ่าน `student_classes` เก็บประวัติความสัมพันธ์เพื่อให้เขียนคิวรีคอร์สเรียนได้ลื่นไหล

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การลืมสร้างดัชนีคุมพิกัดย้อนกลับบน Junction Table ส่งผลให้การ Join ข้อมูลย้อนทางคิวรีทำงานช้าเป็นเต่าคลาน แก้ไขโดยสร้างดัชนีเฉพาะเสริม (Composite Index หรือ Single Index) บนคอลัมน์คีย์นอกตัวที่สองในตารางทางผ่านเสมอ

5. การทำ Denormalization และ Materialized Views สำหรับเอนจิ้น OLAP

ทฤษฎีและกลไกการทำงาน (How it works): ในขณะที่ระบบหลักต้องการการทำ Normalization (แยกตารางเพื่อกันข้อมูลซ้ำ) ระบบประมวลผลเชิงวิเคราะห์ (OLAP) จะกลับขั้วโดยทำ **Denormalization** (การหลอมรวมตารางเข้าด้วยกันล่วงหน้า) เพื่อเลี่ยงคำสั่ง Join สถาปัตยกรรมระดับเอนจิ้นจะใช้ **Materialized Views** ซึ่งจะประมวลผลคิวรีล่วงหน้าและเขียนสรุปบันทึกสเตทลงบนแผ่นดิสก์ถาวรเสมือนตารางจริง ทำให้เวลาเรียกอ่านไม่ต้องประมวลผลใหม่ตั้งแต่ต้นสาย

-- Creating Materialized View on analytical query in ClickHouse
CREATE MATERIALIZED VIEW mv_daily_sales
ENGINE = SummingMergeTree()
PRIMARY KEY (sale_date, product_id)
AS SELECT 
    toDate(created_at) as sale_date,
    product_id,
    sum(amount) as daily_revenue
FROM db.sales
GROUP BY sale_date, product_id;
                    

Use Case ในชีวิตจริง (Real-world Scenario): แดชบอร์ดสรุปยอดผู้เข้าชมเว็บไซต์รายวันดึงข้อมูลจาก Materialized View ที่ประมวลผลสรุปยอดล่วงหน้าจากตารางบันทึกกิจกรรมความละเอียดระดับร้อยกิกะไบต์ ทำให้หน้าแดชบอร์ดโหลดแสดงผลได้ภายในเวลาเสี้ยววินาที

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ในระบบ relational ดั้งเดิม ข้อมูลใน Materialized View จะไม่ยอมรับการอัปเดตแบบเรียลไทม์จนกว่าจะรันคำสั่ง `REFRESH MATERIALIZED VIEW` ซึ่งกินพลังคอมพิวต์สูง แก้ไขโดยใช้เอนจิ้น OLAP อย่าง ClickHouse ที่มีระบบ `SummingMergeTree` คอยอัปเดตพาร์ทิชันสรุปผลอัตโนมัติเมื่อมีข้อมูลใหม่ไหลเข้าท่อ

Data Vault 2.0 (Hubs, Links, Satellites)

ทฤษฎีและกลไกการทำงาน (How it works): Data Vault 2.0 เป็นเทคนิคการทำโมเดลข้อมูลระดับ Enterprise Data Warehouse ที่ออกแบบมาเพื่อรองรับการดึงข้อมูลจากหลายแหล่งที่มีโครงสร้างเปลี่ยนไปมาบ่อยๆ (Agile Data Warehouse) โดยจะแยกโมเดลออกเป็น 3 ประเภทหลัก: - **Hubs**: เก็บเฉพาะกุญแจทางธุรกิจ (Business Keys) และ Hash Key หลัก ไม่มีการเก็บแอตทริบิวต์อื่น - **Links**: เก็บความสัมพันธ์แบบ N:M ระหว่าง Hubs เพื่อสะท้อนเส้นทางกระบวนการธุรกิจ - **Satellites**: เก็บข้อมูลเชิงบรรยาย (Context/Attributes) และประวัติศาสตร์ที่ผูกกับ Hub หรือ Link ทำให้การเปลี่ยนแปลงข้อมูลไม่กระทบแกนกลาง

-- โครงสร้างพื้นฐานของ Data Vault 2.0
CREATE TABLE hub_customer (
  hk_customer_id CHAR(32) PRIMARY KEY, -- MD5 Hash
  customer_business_key VARCHAR(50) NOT NULL,
  load_date TIMESTAMP NOT NULL,
  record_source VARCHAR(50) NOT NULL
);

CREATE TABLE sat_customer_details (
  hk_customer_id CHAR(32) REFERENCES hub_customer(hk_customer_id),
  load_date TIMESTAMP NOT NULL,
  first_name VARCHAR(100),
  last_name VARCHAR(100),
  hash_diff CHAR(32), -- ใช้เทียบเช็คว่าแถวมีข้อมูลเปลี่ยนไหม
  PRIMARY KEY (hk_customer_id, load_date)
);
                    

Use Case ในชีวิตจริง (Real-world Scenario): การควบรวมกิจการของธนาคารสองแห่ง (Mergers and Acquisitions) ทำให้ต้องดึงข้อมูลลูกค้าจากระบบฐานข้อมูลต่างค่ายมารวมกัน Data Vault จะเปิดให้สร้างระบบกลางที่ปรับขยายได้ง่ายโดยไม่ต้องรื้อสคีมาแบบดั้งเดิมทิ้งทั้งหมด

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): โครงสร้าง Data Vault อาศัยการ Join ข้ามตารางจำนวนมหาศาล (Hub + Link + Satellites) ทำให้ประสิทธิภาพการคิวรีอ่านช้ามาก จึงต้องนำไปสร้าง Information Marts เป็นสคีมาดาว (Star Schema) หรือ View ชั้นบนอีกทีให้ผู้ใช้งานใช้

Anchor Modeling

ทฤษฎีและกลไกการทำงาน (How it works): Anchor Modeling คล้ายกับ Data Vault ขั้นสุดยอด (6NF - Sixth Normal Form) ข้อมูลทั้งหมดจะถูกแบ่งแยกออกถึงระดับรายแอตทริบิวต์ (คอลัมน์) แต่ละคอลัมน์จะมีตารางของตัวเองที่ผูกกับตาราง Anchor (แกนหลัก) ข้อดีคือถ้ามีความต้องการเพิ่มคอลัมน์หรือคุณสมบัติใหม่ๆ ในอนาคต (Schema Evolution) ระบบจะไม่ต้อง Alter Table หลักเลย แค่เพิ่มตารางแอตทริบิวต์ใหม่เข้าไป

-- Anchor Modeling Structure
CREATE TABLE anc_employee (  -- Anchor
  emp_id INT PRIMARY KEY
);

CREATE TABLE att_employee_name ( -- Attribute
  emp_id INT REFERENCES anc_employee(emp_id),
  emp_name VARCHAR(100),
  changed_at TIMESTAMP,
  PRIMARY KEY (emp_id, changed_at)
);

CREATE TABLE att_employee_salary ( -- Attribute
  emp_id INT REFERENCES anc_employee(emp_id),
  salary DECIMAL(10,2),
  changed_at TIMESTAMP,
  PRIMARY KEY (emp_id, changed_at)
);
                    

Use Case ในชีวิตจริง (Real-world Scenario): ระบบจัดการข้อมูลด้านสาธารณสุขและระเบียนผู้ป่วย (EHR) ที่คุณสมบัติของผู้ป่วยเพิ่มลดหรือเปลี่ยนแปลงได้บ่อยมากๆ เช่น อาการแพ้ยา ประวัติผ่าตัด ซึ่งไม่ใช่ทุกคนจะมีคอลัมน์เหล่านี้ Anchor Modeling จึงเก็บข้อมูลได้กระชับ (ไม่มี NULL) และประวัติครบถ้วน

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ซับซ้อนมากเกินไปสำหรับโปรเจกต์ขนาดเล็กถึงกลาง การต้องสกัดข้อมูลเพื่อสร้าง Report 1 หน้า อาจต้องเขียน JOIN กว่า 20 ตาราง ทำให้วิศวกรและนักวิเคราะห์มือใหม่สับสน

Slowly Changing Dimensions (SCD) Types 0-6

ทฤษฎีและกลไกการทำงาน (How it works): การจัดการมิติข้อมูลที่มีการเปลี่ยนแปลงตามกาลเวลา (SCD) ใน Dimensional Modeling มีการแบ่งมาตรฐานระดับสูงกว่า Type 1, 2, 3: - **Type 0**: ข้อมูลคงที่ตลอดกาล ห้ามเปลี่ยน (เช่น วันเกิด) - **Type 4**: แยกตาราง History Table ออกไปเลย เพื่อให้ตารางหลักมีเฉพาะค่าปัจจุบันและมีขนาดเล็ก - **Type 5**: ใช้ Type 4 ร่วมกับ Type 1 คือเก็บคีย์อ้างอิงของอดีตในตารางหลักด้วย - **Type 6**: เป็นการรวมร่าง Hybrid ระหว่าง 1, 2, 3 (1+2+3 = 6) คือ เก็บทั้ง Historical Row (Type 2), Current Attribute (Type 1), และ Historical Attribute (Type 3) ไว้ในแถวเดียวกันหมดเพื่อความครบถ้วนสูงสุด

-- SCD Type 6 Dimension Table Example
CREATE TABLE dim_customer_type6 (
  customer_sk INT PRIMARY KEY, -- Surrogate Key
  customer_id VARCHAR(50),     -- Business Key
  current_state VARCHAR(50),   -- Type 1 (อัปเดตทับทั้งหมดเมื่อมีการเปลี่ยน)
  historical_state VARCHAR(50),-- Type 3 (ค่าก่อนหน้าของ Row นี้)
  valid_from DATE,             -- Type 2
  valid_to DATE,               -- Type 2
  is_current BOOLEAN           -- Type 2
);
                    

Use Case ในชีวิตจริง (Real-world Scenario): การทำระบบสถิติประกันภัย ที่ต้องการรู้ทั้งพื้นที่การขายของตัวแทนในอดีต (ณ วันที่ทำประกัน) และพื้นที่รับผิดชอบของตัวแทนคนเดียวกันในปัจจุบัน (ณ วันที่เคลมประกัน) เพื่อวิเคราะห์ความเสี่ยง

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): SCD Type 6 ซับซ้อนในเชิงกระบวนการ ETL เป็นอย่างมาก การรันไปป์ไลน์ต้องเขียนคำสั่ง UPDATE และ INSERT สลับไปมาหลายจังหวะ ทำให้เกิดโอกาสข้อมูลหลุดลอสต์ (Data Anomaly) ได้ง่ายหากกระบวนการล้มเหลวกลางทาง

Junk/Degenerate Dimensions

ทฤษฎีและกลไกการทำงาน (How it works): ในการออกแบบ Star Schema เรามักพบกับคอลัมน์ที่ไม่เหมาะกับการสร้างตาราง Dimension ใหม่ และก็ไม่สามารถไปคำนวณเป็น Fact ได้: - **Degenerate Dimension (DD)**: คอลัมน์ที่ถูกทิ้งไว้ใน Fact Table เลย เช่น หมายเลขใบสั่งซื้อ (Order Number), หมายเลขบิล เพราะไม่มีแอททริบิวต์ย่อยไปขยายต่อแล้ว - **Junk Dimension (JD)**: การรวบรวมฟิลด์สถานะ, แฟล็ก (Flags), หรือค่า Enum เล็กๆ น้อยๆ หลายๆ ตัว (เช่น Yes/No, Status: Pending/Paid) นำมาทำ Cartesian Product แล้วมัดรวมไว้ใน Dimension Table เดียว เพื่อลดจำนวน Foreign Keys ใน Fact Table

-- การสร้าง Junk Dimension ด้วย Cartesian Product (Cross Join)
CREATE TABLE dim_order_status_junk AS
SELECT 
  ROW_NUMBER() OVER() as junk_sk,
  payment_status.status as payment_status,
  shipping_status.status as shipping_status,
  is_expedited.flag as is_expedited
FROM 
  (VALUES ('Pending'), ('Paid'), ('Failed')) payment_status(status)
CROSS JOIN 
  (VALUES ('Packing'), ('Shipped'), ('Delivered')) shipping_status(status)
CROSS JOIN 
  (VALUES (TRUE), (FALSE)) is_expedited(flag);
                    

Use Case ในชีวิตจริง (Real-world Scenario): ตาราง Fact การขนส่งสินค้ามีคอลัมน์สถานะยิบย่อยกว่า 10 คอลัมน์ ทำให้ Fact Table บวมและเปลืองเนื้อที่การตั้ง Index วิศวกรจึงยุบมันเข้าเป็น Junk Dimension ตารางเดียวที่มีแถวประมาณ 500 รูปแบบ (Combinations)

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): หากจำนวนสเตท (Combinations) ของ Junk Dimension มีเยอะมากๆ (เช่น การนำคอลัมน์ 10 ตัวที่มีความเป็นไปได้สูงมาไขว้กัน) จำนวนแถวใน Junk Dimension อาจจะพุ่งทะลุหลักล้านแถว ซึ่งผิดหลักการและกลายเป็นคอขวดเสียเอง

Weekend Sandbox Challenge: Star Schema DDL Design

โจทย์ปฏิบัติการ: จงเขียนรหัส SQL สร้างตารางสัญนิยมแบบจำลองมิติ (Dimensional Modeling) โดยจัดเก็บยอดขายสินค้า ประกอบด้วยตารางยอดทำรายการหลัก (Fact Table) และตารางคุณลักษณะประเภทสินค้าและลูกค้า (Dimension Tables)

-- Create Dim Customers
CREATE TABLE dim_customers (
    customer_key INT PRIMARY KEY,
    customer_id VARCHAR(50) UNIQUE,
    customer_segment VARCHAR(20)
);

-- Create Fact Sales
CREATE TABLE fct_sales (
    sales_key INT PRIMARY KEY,
    date_key INT,
    customer_key INT REFERENCES dim_customers(customer_key),
    amount DECIMAL(12,2),
    quantity INT
);
                    

Senior Technical Interview Q&A

Q1: การออกแบบโมเดลสามมิติแบบ Star Schema (แนวคิด Kimball) มีข้อได้เปรียบเชิงคำนวณการวิเคราะห์อย่างไรเมื่อเทียบกับการออกแบบแบบนอร์มัลไลเซชัน (Inmon)?

A1: Star Schema ออกแบบมาเพื่อเพิ่มความเร็วในการสืบค้นวิเคราะห์เชิงลึก (OLAP) โดยลดจำนวนคำสั่ง JOIN เพื่อให้อ่านประมวลผลข้อมูลได้รวดเร็วขึ้น แม้จะเปลืองดิสก์จากการเก็บข้อมูลซ้ำซ้อนบ้าง (Denormalization) ในขณะที่ Inmon เน้นสถาปัตยกรรมแบบ 3NF เพื่อลดความซ้ำซ้อนประหยัดที่เขียนของ OLTP แต่ต้องใช้จำนวน JOIN มหาศาลวิเคราะห์ช้า

Q2: จงอธิบายวิธีการออกแบบ Slowly Changing Dimension (SCD) Type 2 ในระบบคลังข้อมูล และวิธีคิวรีเพื่อดึงข้อมูลประวัติในอดีต?

A2: SCD Type 2 จัดเก็บประวัติข้อมูลดิบย้อนหลังโดยการสร้างแถวข้อมูลใหม่เมื่อมีการแก้ไขคุณลักษณะ พร้อมเพิ่มคอลัมน์ควบคุม `valid_from`, `valid_to` และ `is_current`. เมื่อต้องการดึงประวัติในอดีต ให้เขียนเงื่อนไขกรอง: `WHERE target_date BETWEEN valid_from AND valid_to` เพื่อให้ได้ค่ามิติ ณ เวลานั้นอย่างถูกต้อง

Q3: Data Vault 2.0 แก้ปัญหาอะไรของ Star Schema แบบดั้งเดิมในบริบทของ Enterprise Data Warehouse ขนาดใหญ่?

A3: Star Schema แบบดั้งเดิมออกแบบบนพื้นฐานของ Business Rules และรวมโครงสร้างข้อมูลให้เรียบง่าย แต่เมื่อระบบต้นทางมีการปรับเปลี่ยน Schema หรือมีการนำเข้า Data Source ใหม่ๆ การปรับแก้ Star Schema จะกระทบโครงสร้างรุนแรง ในขณะที่ Data Vault อาศัยหลักการ Hub-Link-Satellite เพื่อกระจายความสัมพันธ์ เมื่อมี Data Source ใหม่ ก็เพียงแค่เพิ่ม Satellite ใหม่ไปเกาะกับ Hub เดิม โดยไม่ต้องรื้อแก้ Schema เก่า

Interactive Star Schema Designer

Interactive Schema

เป้าหมาย: สร้างความสัมพันธ์แบบ Star Schema โดยจับคู่ Foreign Key จากตารางความจริง (Fact Table) ไปยัง Primary Key ของตารางมิติ (Dimension Tables)

dim_customers Dimension
customer_key PK (Int)
customer_name
country
fact_sales Fact Table
sale_key PK (Int)
customer_key
product_key
amount Metric
dim_products Dimension
product_key PK (Int)
product_name
category

ข้อดี / จุดเด่น & ข้อเสีย / ข้อควรระวัง

ข้อดี / จุดเด่น

  • ช่วยประหยัดเวลาการประมวลผลรายงานวิเคราะห์เพราะการ JOIN ตารางเรียบง่าย
  • รายงานวิเคราะห์อดีตมีความถูกต้อง 100% ไม่สูญเสียประวัติการย้ายหมวดหมู่

ข้อเสีย / ข้อควรระวัง

  • ต้องเขียนโค้ด ETL ที่ซับซ้อนขึ้นในการจัดการคอลัมน์สถานะและช่วงเวลาใช้งาน
  • ตารางบวมและกินพื้นที่ดิสก์เยอะขึ้นเพราะมีการแทรกแถวใหม่ทุกครั้งที่มีการอัปเดต

ปฏิบัติการจริง (Lab Practice)

Bilingual Guide

แล็บ: สร้างแบบจำลองตารางประวัติข้อมูลแบบ SCD Type 2

วิธีรันแล็บปฏิบัติการบนเครื่องจริง (Local Terminal Execution Blueprint)

เนื่องจากปฏิบัติการ Data Engineering / DevOps ระดับสูงต้องรันบน Environment จริง ขั้นตอนด้านล่างนี้คือคำสั่งสำหรับนำไปรันบน Terminal / Docker ในเครื่องของคุณ:

1. สร้างโฟลเดอร์ปฏิบัติการและเตรียมไฟล์ Environment
mkdir -p pipecraft-lab && cd pipecraft-lab
python3 -m venv venv && source venv/bin/activate
pip install --upgrade pip pandas polars pytest requests
2. จำลองการสร้างและรันระบบประมวลผล (Run Pipeline Command)
# Run execution pipeline test
python3 -c "
import polars as pl
print(' [PipeCraft Lab] Running local pipeline engine...')
df = pl.DataFrame({'id': [1, 2, 3], 'status': ['SUCCESS', 'SUCCESS', 'AUDITED']})
print(df)
" 
3. ตรวจสอบการผ่านเกณฑ์และการทำงาน (Data Quality Assertions)
# Verify clean execution exit status
echo " PipeCraft Local Lab Execution Completed Successfully!"

💡 คำแนะนำ & ทริกเด็ด

หลีกเลี่ยงการใช้ SCD Type 2 กับตารางมิติที่มีขนาดขยายตัวเร็วมาก (High-Cardinality) เพราะจำนวนแถวจะบวมขึ้นเรื่อยๆ แนะนำให้แยกฟิลด์ที่เปลี่ยนบ่อยออกไปเป็นตารางย่อยแยกต่างหาก