MODUL 1 - LEKCIJA 3

Napredni Dizajn: Temporal Tables & Partitioning

Ekspertsko upravljanje historijom podataka i optimizacija storage-a velikih razmjera

⏱️ Trajanje: ~4 časa 📚 Nivo: Napredni 🎯 Praktični primjeri: 7

📖 Izvan osnovnog skladištenja

U savremenom razvoju softvera, podaci nisu statični. Zahtjevi za auditom (ko je šta promijenio i kada) i upravljanje tabelama sa stotinama miliona redova zahtijevaju tehnologije koje prevazilaze standardni CREATE TABLE. SQL Server 2022 nudi Temporal Tables za automatsko verziranje i Partitioning za inteligentno podjelu podataka.

⏱️ Temporal Tables (System-Versioned Internals)

Temporalna tabela je zapravo par tabela: trenutna tabela (koju koristite za rad) i historijska tabela (koju engine koristi za čuvanje starih verzija redova).

Kako to radi "ispod haube"?

🛠️ Kreiranje sa Ručno Definisanim Historijskim Storage-om
-- Preporuka: Uvijek koristite PAGE kompresiju na historijskoj tabeli jer se rijetko mijenja
CREATE TABLE Procurement.Vendors (
    VendorID INT PRIMARY KEY IDENTITY(1,1),
    VendorName NVARCHAR(200) NOT NULL,
    DiscountPct DECIMAL(5,2) NOT NULL,
    -- Period kolone su obavezne
    ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,
    ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
    PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (
    HISTORY_TABLE = Procurement.Vendors_History,
    DATA_CONSISTENCY_CHECK = ON
));
GO

🎯 Zašto HIDDEN kolone?

Koristimo ključnu riječ HIDDEN kako bi SELECT * upiti ostali čisti i ne bi prikazivali tehničke kolone validnosti osim ako ih specifično ne tražimo.

🗜️ Data Compression: Page-Level Deep Dive

Dok Row kompresija štedi bajtove unutar reda, Page Compression radi na nivou cijele 8KB stranice koristeći dva procesa:

  1. Prefix Compression: Ako kolona u više redova na jednoj stranici počinje istim karakterima (npr. 'Sarajevo, 'Sarajevo 1'), SQL Server čuva prefiks samo jednom.
  2. Dictionary Compression: Traži identične vrijednosti bilo gdje na stranici i mijenja ih kratkim tokenima.

⚠️ CPU vs I/O Tradeoff

Kompresija zahtijeva CPU cikluse za otpakivanje podataka u RAM-u. Međutim, pošto je I/O (čitanje sa diska) skoro uvijek usko grlo, kompresija obično poboljšava ukupne performanse sistema.

🧩 Table Partitioning: Strategija "Divide and Conquer"

Particionisanje nije samo za prostor. To je alat za Data Lifecycle Management (DLM).

Komponente Particionisanja:

⚡ Sliding Window: Switching Partitions
-- Zamislite da imamo milione redova u tabeli 'Logs' za 2023. godinu.
-- Umjesto sporog 'DELETE FROM Logs WHERE Year = 2023', radimo SWITCH:

-- 1. Napravimo identičnu praznu tabelu 'Logs_Archive_2023'
-- 2. "Prebacimo" particiju (to je samo metadata promjena u engine-u)
ALTER TABLE Logs SWITCH PARTITION 1 TO Logs_Archive_2023;

-- Trajanje: ~10ms bez obzira na broj redova (100 miliona ili 100 redova).

🎯 Praktična Vježba: Totalna Optimizacija

Zadatak: Dizajniranje "Big Data" Tabele za Transakcije

Aplikacija bilježi 10 miliona transakcija mjesečno. Moramo osigurati da sistem ostane brz i da možemo lako arhivirati stare podatke.

Zadatak 1: Kreirajte Partition Function po mjesecima za 2025. godinu.

Zadatak 2: Kreirajte tabelunad tom shemom sa uključenom PAGE kompresijom.

Zadatak 3: Omogućite System Versioning za audit promjena statusa transakcija.

💡 Ekspertsko Rješenje
-- 1. Funkcija
CREATE PARTITION FUNCTION pf_Monthly (DATE)
AS RANGE RIGHT FOR VALUES ('2025-02-01', '2025-03-01', '2025-04-01');
GO

-- 2. Shema (Mapiramo sve na PRIMARY radi jednostavnosti vježbe)
CREATE PARTITION SCHEME ps_Monthly AS PARTITION pf_Monthly ALL TO ([PRIMARY]);
GO

-- 3. Tabela sa svim "naprednim" začinima
CREATE TABLE Financial.Transactions (
    TransID BIGINT IDENTITY(1,1),
    Amount DECIMAL(18,2) NOT NULL,
    TransDate DATE NOT NULL,
    Status NVARCHAR(20),
    ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,
    ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
    PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo),
    CONSTRAINT PK_Transactions PRIMARY KEY (TransID, TransDate) -- PK mora sadržavati partition key
)
ON ps_Monthly (TransDate)
WITH (
    SYSTEM_VERSIONING = ON (HISTORY_TABLE = Financial.Transactions_History),
    DATA_COMPRESSION = PAGE
);
GO

✅ Zaključak

Napredni dizajn tabela transformiše vašu bazu iz pasivnog spremišta u inteligentan sistem:

📚 Sljedeća Lekcija

U Lekciji 1.4 zaključujemo Modul 1 fokusirajući se na Integritet Podataka i kako mehanizmi baze garantuju da nikada ne dobijete "siroče" u podacima.