Tabele faktów i wymiarów
Elementy składowe hurtowni danych
Tabele faktów i wymiarów to bezpłatna lekcja SQL Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Academy zawiera 4 lekcji w sumie.
Czym jest hurtownia danych?
Hurtownia danych to centralne repozytorium przeznaczone do raportowania i wykonywania zapytań analitycznych. W przeciwieństwie do bazy transakcyjnej, zoptymalizowanej pod kątem szybkich zapisów, hurtownia jest dostrojona do szybkiego odczytu dużych ilości danych historycznych.
Najczęstszym sposobem organizowania hurtowni jest użycie schematu gwiazdy, który dzieli dane na dwa typy tabel: tabele faktów i tabele wymiarów.
Definicja tabel faktów
Tabela faktów przechowuje mierzalne, ilościowe zdarzenia — informacje, które chcą Państwo analizować. Każdy wiersz reprezentuje jedno wystąpienie zdarzenia biznesowego, takiego jak sprzedaż, wyświetlenie strony internetowej lub zgłoszenie do pomocy technicznej.
Tabele faktów są zazwyczaj długie (wiele wierszy) i wąskie (niewiele kolumn), przy czym większość kolumn to klucze obce wskazujące tabele wymiarów albo miary liczbowe, takie jak quantity lub revenue.
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,
unit_price NUMERIC(10, 2) NOT NULL,
total_amount NUMERIC(12, 2) NOT NULL
);Definicja tabel wymiarów
Tabela wymiarów przechowuje atrybuty opisowe, które nadają kontekst poszczególnym faktom. Przykładami są wymiar produktu (nazwa, kategoria, marka) oraz wymiar daty (dzień, miesiąc, kwartał, rok).
Tabele wymiarów są zwykle krótkie (mają mniej wierszy), ale szerokie (zawierają wiele kolumn opisowych). Są łączone z tabelą faktów za pomocą całkowitoliczbowych kluczy zastępczych.
CREATE TABLE dim_product (
product_key SERIAL PRIMARY KEY,
product_name VARCHAR(200) NOT NULL,
category VARCHAR(100),
brand VARCHAR(100),
unit_cost NUMERIC(10, 2)
);
CREATE TABLE dim_customer (
customer_key SERIAL PRIMARY KEY,
full_name VARCHAR(200) NOT NULL,
email VARCHAR(200),
country VARCHAR(100),
segment VARCHAR(50)
);Wymiar daty
Wymiar daty jest najczęściej używanym wymiarem w każdej hurtowni danych. Zamiast przechowywać surową wartość TIMESTAMP w tabeli faktów, przechowuje się klucz całkowitoliczbowy wskazujący wstępnie utworzoną tabelę kalendarza.
Dzięki temu zapytania mogą filtrować dane lub grupować je według kwartału fiskalnego, dnia tygodnia, oznaczenia święta i innych atrybutów kalendarza bez wykonywania operacji na datach w czasie zapytania.
CREATE TABLE dim_date (
date_key INT PRIMARY KEY, -- e.g. 20240315
full_date DATE NOT NULL,
day_of_week VARCHAR(10),
day_of_month INT,
month_num INT,
month_name VARCHAR(20),
quarter INT,
year INT,
is_holiday BOOLEAN DEFAULT FALSE,
fiscal_quarter INT
);
-- Sample row
INSERT INTO dim_date VALUES
(20240315, '2024-03-15', 'Friday', 15, 3, 'March', 1, 2024, FALSE, 2);Wzorzec schematu gwiazdy
Gdy na diagramie narysują Państwo jedną tabelę faktów w centrum oraz tabele wymiarów rozchodzące się na zewnątrz, całość przypomina gwiazdę — stąd nazwa schemat gwiazdy.
Klucze obce w tabeli faktów wskazują klucze główne poszczególnych wymiarów. Zapytania zwykle łączą tabelę faktów z jednym lub większą liczbą wymiarów, aby dodać opisowy kontekst do surowych wartości liczbowych.
-- Join fact to two dimensions to enrich a sales report
SELECT
dp.product_name,
dp.category,
SUM(fs.quantity) AS total_units_sold,
SUM(fs.total_amount) AS total_revenue
FROM fact_sales fs
JOIN dim_product dp ON dp.product_key = fs.product_key
JOIN dim_date dd ON dd.date_key = fs.date_key
WHERE dd.year = 2024
GROUP BY dp.product_name, dp.category
ORDER BY total_revenue DESC;Klucze zastępcze a klucze naturalne
Tabele wymiarów używają kluczy zastępczych — sztucznych liczb całkowitych generowanych przez bazę danych, niezależnych od jakiegokolwiek znaczenia biznesowego. Klucze naturalne (takie jak SKU produktu lub adres e-mail klienta) mogą z czasem ulegać zmianie, ale klucze zastępcze pozostają niezmienne.
Użycie kluczy zastępczych izoluje tabelę faktów od zmian w systemach źródłowych i przyspiesza złączenia, ponieważ porównywanie liczb całkowitych jest tańsze niż porównywanie ciągów znaków.
-- Surrogate key approach: integer join is fast
SELECT fs.sale_id, dc.full_name, fs.total_amount
FROM fact_sales fs
JOIN dim_customer dc ON dc.customer_key = fs.customer_key
WHERE dc.country = 'Germany'
LIMIT 10;
-- Natural key approach (avoid in warehouses): slower string join
-- JOIN dim_customer dc ON dc.email = fs.customer_emailZiarno: poziom szczegółowości w tabeli faktów
Ziarno tabeli faktów dokładnie określa, co reprezentuje jeden wiersz. Przed zbudowaniem hurtowni należy określić ziarno — na przykład jeden wiersz na pojedynczą pozycję produktu w zamówieniu sprzedaży.
Dobrze zdefiniowane ziarno zapobiega niejednoznacznym agregacjom. Jeśli różne wiersze reprezentują różne zdarzenia, wyniki funkcji SUM i COUNT będą pozbawione znaczenia.
-- Grain: one row per product per order line
-- Each row = one line item sold in one transaction
SELECT
sale_id,
date_key,
product_key,
quantity,
unit_price,
total_amount
FROM fact_sales
WHERE date_key = 20240315
ORDER BY sale_id;Miary addytywne, częściowo addytywne i nieaddytywne
Fakty dzielą się na trzy kategorie w zależności od sposobu ich agregowania:
- Addytywne — można je sumować we wszystkich wymiarach (np.
revenue,quantity). - Częściowo addytywne — można je sumować w niektórych wymiarach, ale nie we wszystkich (np.
balancekonta można sumować według klientów, ale nie według czasu). - Nieaddytywne — nie można ich sensownie sumować (np.
unit_price,ratio). Zamiast tego należy użyć funkcji AVG lub innych agregacji.
SELECT
dd.month_name,
SUM(fs.total_amount) AS total_revenue, -- additive
AVG(fs.unit_price) AS avg_unit_price, -- non-additive: use AVG
SUM(fs.quantity) AS total_units -- additive
FROM fact_sales fs
JOIN dim_date dd ON dd.date_key = fs.date_key
WHERE dd.year = 2024
GROUP BY dd.month_name, dd.month_num
ORDER BY dd.month_num;Wolno zmieniające się wymiary (SCD typu 1 i 2)
Atrybuty wymiarów zmieniają się z czasem — klient zmienia kraj, a produkt kategorię. Wolno zmieniające się wymiary (SCD) obsługują te zmiany:
- Typ 1 — nadpisanie starej wartości. To proste rozwiązanie, ale historia zostaje utracona.
- Typ 2 — dodanie nowego wiersza z nowym kluczem zastępczym i datami obowiązywania. Zachowuje pełną historię, dzięki czemu fakty historyczne nadal wskazują właściwą wersję wymiaru.
-- SCD Type 2: add a new version of the row
ALTER TABLE dim_customer ADD COLUMN valid_from DATE;
ALTER TABLE dim_customer ADD COLUMN valid_to DATE;
ALTER TABLE dim_customer ADD COLUMN is_current BOOLEAN DEFAULT TRUE;
-- Expire the old row
UPDATE dim_customer
SET is_current = FALSE,
valid_to = CURRENT_DATE - INTERVAL '1 day'
WHERE email = 'anna@example.com' AND is_current = TRUE;
-- Insert the updated version
INSERT INTO dim_customer (full_name, email, country, segment, valid_from, valid_to, is_current)
VALUES ('Anna Muller', 'anna@example.com', 'Austria', 'Premium', CURRENT_DATE, '9999-12-31', TRUE);Wymiary zdegenerowane
Czasami atrybut wymiaru nie wymaga własnej tabeli. Wymiar zdegenerowany to klucz wymiaru znajdujący się bezpośrednio w tabeli faktów, bez odpowiadającej mu tabeli wymiaru.
Klasycznymi przykładami są numery zamówień, numery faktur lub identyfikatory zgłoszeń. Zapewniają one kontekst podczas drążenia danych, ale nie mają innych opisowych kolumn, które warto byłoby przechowywać w oddzielnej tabeli.
-- order_number is a degenerate dimension:
-- it lives in the fact table, no dim_order table needed
CREATE TABLE fact_order_lines (
line_id SERIAL PRIMARY KEY,
order_number VARCHAR(20) NOT NULL, -- degenerate dimension
date_key INT NOT NULL,
product_key INT NOT NULL,
customer_key INT NOT NULL,
quantity INT NOT NULL,
line_total NUMERIC(12, 2) NOT NULL
);
SELECT order_number, SUM(line_total) AS order_total
FROM fact_order_lines
GROUP BY order_number
ORDER BY order_total DESC
LIMIT 5;Zapytania w pełnym schemacie gwiazdy
Podsumowując: typowe zapytanie do hurtowni łączy tabelę faktów z kilkoma wymiarami, stosuje filtry dotyczące atrybutów wymiarów i agreguje miary z tabeli faktów.
Optymalizator może wydajnie obsługiwać te złączenia wielostronne, ponieważ klucze obce tabeli faktów są indeksowane, a tabele wymiarów są stosunkowo małe.
SELECT
dd.year,
dd.quarter,
dp.category,
dc.country,
SUM(fs.quantity) AS units_sold,
SUM(fs.total_amount) AS revenue
FROM fact_sales fs
JOIN dim_date dd ON dd.date_key = fs.date_key
JOIN dim_product dp ON dp.product_key = fs.product_key
JOIN dim_customer dc ON dc.customer_key = fs.customer_key
WHERE dd.year IN (2023, 2024)
AND dp.category = 'Electronics'
GROUP BY dd.year, dd.quarter, dp.category, dc.country
ORDER BY dd.year, dd.quarter, revenue DESC;Szybkie sprawdzenie: fakt czy wymiar
Proszę sprawdzić swoją wiedzę na temat różnic między tabelami faktów i tabelami wymiarów w schemacie gwiazdy.
Podsumowanie lekcji
W tej lekcji poznali Państwo podstawowe elementy schematu gwiazdy w hurtowni danych:
- Tabele faktów przechowują mierzalne zdarzenia (sprzedaż, kliknięcia, transakcje) wraz z miarami liczbowymi i kluczami obcymi.
- Tabele wymiarów dostarczają opisowego kontekstu (kto, co, gdzie, kiedy) i korzystają z kluczy zastępczych.
- Ziarno dokładnie określa, co reprezentuje jeden wiersz faktów — należy je określić przed rozpoczęciem budowy.
- Miary mogą być addytywne, częściowo addytywne lub nieaddytywne, co decyduje o sposobie ich agregowania.
- SCD typu 2 zachowuje historyczne wartości wymiarów, dodając nowe wiersze z datami obowiązywania.
- Wymiary zdegenerowane znajdują się w tabeli faktów, gdy nie mają dodatkowych atrybutów opisowych.
Zrozumienie tabel faktów i tabel wymiarów stanowi podstawę budowania szybkich, skalowalnych i wydajnych analitycznie hurtowni danych.
Często zadawane pytania
Czy lekcja „Tabele faktów i wymiarów” jest bezpłatna?
Tak — pełny tekst „Tabele faktów i wymiarów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Academy, przejdź na CoddyKit PRO. Kurs SQL Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Tabele faktów i wymiarów”?
Elementy składowe hurtowni danych Ćwiczysz SQL Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Academy?
Nie wymagamy żadnego doświadczenia. SQL Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Tabele faktów i wymiarów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Academy?
Tak. Każda lekcja SQL Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- OLTP a OLAP
- Tabele faktów i wymiarów
- Schematy gwiazdy i płatka śniegu
- Pisanie zapytań analitycznych