SQL Academy · บทเรียน

สคีมาแบบดาวและแบบเกล็ดหิมะ

จำลองข้อมูลเพื่อการวิเคราะห์ที่รวดเร็ว

บทเรียน 3 จาก 413 ขั้นตอน

สคีมาแบบดาวและแบบเกล็ดหิมะ เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

สคีมาคลังข้อมูลคืออะไร

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

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

ตารางข้อเท็จจริงและตารางมิติ

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

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

CREATE TABLE fact_sales (
  sale_id      SERIAL PRIMARY KEY,
  date_key     INT NOT NULL,
  product_key  INT NOT NULL,
  customer_key INT NOT NULL,
  store_key    INT NOT NULL,
  quantity     INT NOT NULL,
  revenue      NUMERIC(12, 2) NOT NULL
);

CREATE TABLE dim_product (
  product_key  SERIAL PRIMARY KEY,
  product_name VARCHAR(200),
  category     VARCHAR(100),
  brand        VARCHAR(100),
  unit_price   NUMERIC(10, 2)
);

สคีมาแบบดาว

ใน สคีมาแบบดาว ตารางมิติทุกตารางเชื่อมต่อกับตารางข้อเท็จจริง โดยตรง หากวาดความสัมพันธ์ลงบนกระดาษ จะดูเหมือนดาว โดยมีตารางข้อเท็จจริงเป็นจุดศูนย์กลางและตารางมิติเป็นแฉก

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

-- Star schema: all product info in one flat dimension table
CREATE TABLE dim_product (
  product_key    SERIAL PRIMARY KEY,
  product_name   VARCHAR(200),
  category_name  VARCHAR(100),   -- denormalized
  subcategory    VARCHAR(100),   -- denormalized
  brand_name     VARCHAR(100),   -- denormalized
  brand_country  VARCHAR(100),   -- denormalized
  unit_price     NUMERIC(10, 2)
);

CREATE TABLE dim_date (
  date_key   INT PRIMARY KEY,   -- e.g. 20240315
  full_date  DATE,
  year       INT,
  quarter    INT,
  month      INT,
  month_name VARCHAR(20),
  week       INT,
  day_of_week VARCHAR(10)
);

คำสั่งสืบค้นสคีมาแบบดาว

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

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

SELECT
  d.year,
  d.quarter,
  p.category_name,
  SUM(f.revenue)   AS total_revenue,
  SUM(f.quantity)  AS units_sold
FROM fact_sales f
JOIN dim_date    d ON d.date_key    = f.date_key
JOIN dim_product p ON p.product_key = f.product_key
WHERE d.year = 2024
GROUP BY d.year, d.quarter, p.category_name
ORDER BY d.quarter, total_revenue DESC;

สคีมาแบบเกล็ดหิมะ

สคีมาแบบเกล็ดหิมะทำให้ตารางมิติเป็นรูปแบบปกติมากขึ้นด้วยการแบ่งตารางออกเป็นมิติย่อย ตัวอย่างเช่น แทนที่จะจัดเก็บ category_name และ brand_name ไว้ใน dim_product คุณจะสร้างตาราง dim_category และ dim_brand แยกกัน

แผนภาพที่ได้จะดูคล้ายเกล็ดหิมะ ซึ่งมีแขนงของตารางที่เกี่ยวข้องแตกออกจากกัน

-- Snowflake schema: product dimension is normalized
CREATE TABLE dim_brand (
  brand_key     SERIAL PRIMARY KEY,
  brand_name    VARCHAR(100),
  brand_country VARCHAR(100)
);

CREATE TABLE dim_category (
  category_key   SERIAL PRIMARY KEY,
  category_name  VARCHAR(100),
  subcategory    VARCHAR(100)
);

CREATE TABLE dim_product (
  product_key  SERIAL PRIMARY KEY,
  product_name VARCHAR(200),
  category_key INT REFERENCES dim_category(category_key),
  brand_key    INT REFERENCES dim_brand(brand_key),
  unit_price   NUMERIC(10, 2)
);

คิวรีสคีมาแบบเกล็ดหิมะ

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

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

SELECT
  d.year,
  c.category_name,
  b.brand_name,
  SUM(f.revenue) AS total_revenue
FROM fact_sales    f
JOIN dim_date      d ON d.date_key    = f.date_key
JOIN dim_product   p ON p.product_key = f.product_key
JOIN dim_category  c ON c.category_key = p.category_key
JOIN dim_brand     b ON b.brand_key    = p.brand_key
WHERE d.year = 2024
GROUP BY d.year, c.category_name, b.brand_name
ORDER BY total_revenue DESC;

คีย์ตัวแทนเทียบกับคีย์ธรรมชาติ

โดยทั่วไปตารางมิติจะใช้ คีย์ตัวแทน ซึ่งเป็นจำนวนเต็มที่คลังข้อมูลสร้างขึ้น (เช่น SERIAL) แทนคีย์ธรรมชาติจากระบบต้นทาง

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

-- Surrogate key (product_key) vs natural key (sku)
INSERT INTO dim_product (product_name, category_key, brand_key, unit_price)
VALUES ('Wireless Headphones', 3, 7, 89.99);
-- product_key is assigned by SERIAL -- the natural key (SKU) lives elsewhere

-- Natural key would be:
-- INSERT INTO dim_product (sku, product_name, ...)
-- VALUES ('WH-1000XM5', 'Wireless Headphones', ...);
-- Risky: SKU can be reused or reassigned by the source system

มิติวันที่

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

-- Populate dim_date for one year using generate_series
INSERT INTO dim_date (date_key, full_date, year, quarter, month, month_name, week, day_of_week)
SELECT
  TO_CHAR(d, 'YYYYMMDD')::INT  AS date_key,
  d                             AS full_date,
  EXTRACT(YEAR    FROM d)::INT  AS year,
  EXTRACT(QUARTER FROM d)::INT  AS quarter,
  EXTRACT(MONTH   FROM d)::INT  AS month,
  TO_CHAR(d, 'Month')           AS month_name,
  EXTRACT(WEEK    FROM d)::INT  AS week,
  TO_CHAR(d, 'Day')             AS day_of_week
FROM generate_series('2024-01-01'::DATE, '2024-12-31'::DATE, '1 day') AS d;

มิติที่เปลี่ยนแปลงช้า (SCD ประเภท 2)

จะเกิดอะไรขึ้นเมื่อลูกค้าย้ายเมืองหรือสินค้าเปลี่ยนหมวดหมู่ คุณต้องติดตามประวัติ SCD ประเภท 2จะแทรกแถวมิติใหม่สำหรับการเปลี่ยนแปลงแต่ละครั้ง พร้อมปิดแถวก่อนหน้าด้วยวันที่สิ้นสุด แถวในตารางข้อเท็จจริงยังคงชี้ไปยังคีย์มิติเดิม จึงรักษาความถูกต้องของข้อมูลในอดีตไว้ได้

-- SCD Type 2 customer dimension
CREATE TABLE dim_customer (
  customer_key  SERIAL PRIMARY KEY,
  customer_id   INT NOT NULL,
  customer_name VARCHAR(200),
  city          VARCHAR(100),
  country       VARCHAR(100),
  valid_from    DATE NOT NULL,
  valid_to      DATE,
  is_current    BOOLEAN DEFAULT TRUE
);

-- When a customer moves, close old row and insert new one:
UPDATE dim_customer
   SET valid_to = CURRENT_DATE - 1, is_current = FALSE
 WHERE customer_id = 42 AND is_current = TRUE;

INSERT INTO dim_customer (customer_id, customer_name, city, country, valid_from, is_current)
VALUES (42, 'Alice Muller', 'Berlin', 'Germany', CURRENT_DATE, TRUE);

สคีมาแบบดาวเทียบกับแบบเกล็ดหิมะ — ข้อแลกเปลี่ยน

ไม่มีสคีมาใดดีกว่าเสมอไป ให้เลือกตามลำดับความสำคัญของคุณ:

  • แบบดาว — การเชื่อมตารางน้อยกว่า คิวรีเร็วกว่า ETL ง่ายกว่า แต่มีค่าใช้พื้นที่จัดเก็บสูงกว่า เหมาะที่สุดสำหรับเครื่องมือวิเคราะห์ที่อ่านข้อมูลเป็นหลัก เช่น Tableau และ Power BI
  • แบบเกล็ดหิมะ — มิติเป็นรูปแบบปกติ มีข้อมูลซ้ำซ้อนน้อยกว่า และอัปเดตมิติได้ง่ายกว่า แต่ต้องเชื่อมตารางมากกว่า เหมาะกว่าเมื่อมิติมีขนาดใหญ่หรือใช้ร่วมกันในตารางข้อเท็จจริงหลายตาราง
-- Checking how much storage the denormalized category column costs
-- in a large dim_product (star schema) vs a separate dim_category (snowflake)
SELECT
  COUNT(*)                               AS total_products,
  COUNT(DISTINCT category_name)          AS unique_categories,
  pg_size_pretty(
    SUM(pg_column_size(category_name))
  )                                      AS category_storage
FROM dim_product;

สคีมาแบบกาแล็กซี (กลุ่มดาวของตารางข้อเท็จจริง)

เมื่อคลังข้อมูลมีตารางข้อเท็จจริงหลายตารางที่ใช้ตารางมิติร่วมกัน ผลลัพธ์จะเรียกว่า สคีมาแบบกาแล็กซี (หรือกลุ่มดาวของตารางข้อเท็จจริง) ตัวอย่างเช่น คลังข้อมูลค้าปลีกอาจมีตารางข้อเท็จจริงแยกกันสำหรับยอดขายและการคืนสินค้า โดยทั้งสองตารางอ้างอิง dim_product และ dim_date เดียวกัน

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

CREATE TABLE fact_returns (
  return_id     SERIAL PRIMARY KEY,
  date_key      INT NOT NULL REFERENCES dim_date(date_key),
  product_key   INT NOT NULL REFERENCES dim_product(product_key),
  customer_key  INT NOT NULL,
  quantity      INT NOT NULL,
  refund_amount NUMERIC(12, 2) NOT NULL
);

-- Cross-fact query: net revenue = sales - refunds
SELECT
  d.year,
  d.month,
  SUM(s.revenue)       AS gross_revenue,
  SUM(r.refund_amount) AS total_refunds,
  SUM(s.revenue) - COALESCE(SUM(r.refund_amount), 0) AS net_revenue
FROM dim_date d
LEFT JOIN fact_sales   s ON s.date_key = d.date_key
LEFT JOIN fact_returns r ON r.date_key = d.date_key
WHERE d.year = 2024
GROUP BY d.year, d.month
ORDER BY d.month;

สคีมาแบบดาวเทียบกับแบบเกล็ดหิมะ

ทดสอบความเข้าใจของคุณเกี่ยวกับสคีมาแบบดาวและแบบเกล็ดหิมะ

สรุปบทเรียน

ในบทเรียนนี้ คุณได้สำรวจรูปแบบการออกแบบคลังข้อมูลพื้นฐานสองรูปแบบ:

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

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

เริ่มต้นได้ฟรี

เรียนรู้ SQL ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
46
บทเรียน
183

คำถามที่พบบ่อย

บทเรียน “สคีมาแบบดาวและแบบเกล็ดหิมะ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “สคีมาแบบดาวและแบบเกล็ดหิมะ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “สคีมาแบบดาวและแบบเกล็ดหิมะ”

จำลองข้อมูลเพื่อการวิเคราะห์ที่รวดเร็ว คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “สคีมาแบบดาวและแบบเกล็ดหิมะ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม

ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. OLTP เทียบกับ OLAP
  2. ตารางข้อเท็จจริงและตารางมิติ
  3. สคีมาแบบดาวและแบบเกล็ดหิมะ
  4. การเขียนคำค้นหาเชิงวิเคราะห์
← กลับไปที่ SQL Academy