# 4. Databáze
Principy ukládání dat, databáze. Architektura relačních databází, dotazovací jazyk SQL a jeho části (definice, manipulace, transakce). Jazyk definice datového schématu, DDL. Jazyk manipulace s daty, DML. Relační algebra, integritní omezení, řízení transakcí. Indexování, hašování. Příklady z praxe pro vše výše uvedené. (PV003, PA152)
---
**Dáta** sú údaje, ktoré majú určitú výpovednú hodnotu.
- Môžu byť usporiadané (štruktúrované), ale aj nemusia byť
- Užívateľovi sú k dispozícií v rôznych formách
- Tabulky, grafy, súbory, obrazy, vektory, matice, ...
## Princípy ukladania dát, databáze
### Princípy ukladania dát
Dáta vieme ukladať do súborového systému v rámci **súborovej štruktúry** alebo do **databázového systému** (relačné, dokumentové, grafové, vektorové), ktorý dáta logicky zoskupuje a snaží sa zabezpečiť efektívny prístup k dátam z pohľadu rýchlosti a spolahlivosti a konzistencie dát.
**Súborový systém** využívame zvyčajne na ukladanie neštruktúrovaných dát alebo súborov, napríklad obrázky uploadované skrz webové rozhranie. Vieme využiť cloudové úložiská (Amazon S3 Cloud Storage), lokálne HDD/SSD disky, prípadne zoskupenie diskov skrz RAID. Súborový systém nám zabezpečuje operačný systém a zvolený súborový systém - napr. FAT32, NTFS, EXT4, Btrfs.
- Výhody: menšie systémové nároky, jednoduché na používanie aplikáciami
- Nevýhody: náročné na zaistenie konzistencie, nutnosť riešiť zamýkanie súborov, problematický prístup k transakciám (prepisovanie súborov a riešenie prístupových práv), horšia čitateľnosť a dokumentácia súborového systému
### Databáze
**Databáza** je usporiadaná množina dát.
- Prístup k uloženým dátam obstaráva **databázový menežmentový systém** (DBMS)
- Databáza spoločne s DBMS tvorí **databázový systém**
- Dáta vieme dotazovať pomocou dotazovacieho jazyka (napr. SQL)
- **Účelom** databázových systémov je **riešit problémy** efektivity, redundancie dát, inkonzistencie, integrity a bezpečnosti
- Štruktúry dát sú uložené oddelene od súborov na disku
- Prístup k dátam je možný len prostredníctvom DBMS
- Dáta je možné vyhodnocovať pomocou vhodných jazykov alebo metód
- Je umožnený prístup viacerých užívateľov, ich správa a oprávnenia
- Problémy inkonzistencie riešia **transakcie** a systém ich vyhodnocovania a plánovania
- Väčšinou chceme, aby transakcie spĺňali **ACID** vlastnosti [Riadenie transakcii](/4fglZcU1QnGSdEthNGIEEQ?#Riadenie-transakcií)
Rozlišujeme **typy** databázových systémov:
- Relačné
- dáta sú štruktúrované, ukladané v tabuľkách
- dáta podliehajú normálovým formám
- používa jazyk SQL, ktorý vychádza z relačnej algebry
- často používa dátové štruktúry ako napríklad B+ stromy, červeno-čierne stromy, R stromy
- používa modelovanie schém pomocou UML ERD diagramu
- Not only SQL (NoSQL)
- vznikli kvôli potrebe horizontálne škálovať
- XML databázy, MongoDB (document-based), Redis (caching, key-value)
- grafové, vektorové, dokumentové ...
- dáta nemusia mať nejakú štruktúru, nepodliehaju normám
- Napríklad MongoDB poskytuje ACID transakcie, ale nie je to bežné u iných DBMS
- v dnešnej dobe často podporované aj v relačných DBMS (Postgres, MSSQL)
- Podpora pre neštrukturovaný JSON, BSON
- CAP theorem
- Pre distribuovaný systém nie je možné poskytovať zároveň konzistenciu dát naprieč clustermi (Consistency), dostupnosť odpovedí node-ov (Availability) a toleranciu prerušenia komunikácie clusterov (Partition tolerance)
- NoSQL databázy používajú Eventual Consistency - ak nenastávajú po nejakú dobu zmeny, tak v tom momente sa stáva databáza konzistentnou
- NewSQL - relačné DBMS, kombinuje flexibilitu NoSQL pre OLTP
- Coachbase, VoltDB, CockroachDB
- Hybrid Transactional-Analytical Processing (HTAP)
Dáta môžu byť ukládané v rôznej orientácii, rozlišujeme kvôli efektivite operácií nad nimi:
- row-oriented
- OLTP (online transaction processing) - klasické RDBMS (MySQL, MSSQL, Postgres, MariaDB, SQLite)
- sú vhodné na rýchly prístup k filtrovaným dátam pomocou WHERE a INSERT nových riadkov
- column-oriented
- sú vhodné na OLAP - analytické databázy napr. DuckDB, RedShift, R dataframes, Pandas
- rýchly prístup k výsledkom projekcie - SELECT ... FROM, pridávanie stĺpcov
- majú lepšiu kompresiu - používajú Run-Length encoding, bitmapy
## Architektúra relačných databáz, dotazovací jazyk SQL a jeho časti (definícia, manipulácia, transakcia)
### Architektúra relačných databáz
**Model dát** je sada nástrojov pre popis dát (syntax a sémantika), vzťahov medzi dátami a podmienkami, ktoré nad nimi platia.
**Relačný model dát** je databázový model založený na **predikátovej logike**.
- Základným princípom je, že všetky dáta sú reprezentované pomocou $n$-árnych relácií
- Na dátach sa operuje pomocou **relačnej algebry**
- Databáze organizované pomocou relačného modelu sa nazývajú **relačné databáze**
**Relačný model dát** sa skladá z nasledujúcich častí:
- **Atribút** - charakteristika, vlastnosť objektu
- Popísaný nejakou **hodnotou**
- Hodnota atribútu má **dátový typ**
- **Doména** - neprázdna množina hodnôt dátového typu atribútu
- Súčasťou každej domény je hodnota $null$
- Doména určuje povolené hodnoty pre daný atribút
- **Relácia** - podmnožina kartézskeho súčinu $n$ domén
- Podmnožina $n$-tíc atribútov
- Nesmie obsahovať duplicitné relácie
- Pokiaľ rôzne relácie obsahujú rovnaký atribút, môže medzi nimi vzinknúť väzba
- Kedže je to množina, nezávisí na poradí $n$-tíc
- Prázdna relácia je validná
- **Relačná schéma** - $n$-tica atribútov
- Určuje názov a záhlavie tabuľky
- Koľko má stĺpcov a ako sa volajú
- **Tabuľka** je reprezentáciou relácie
- Prázdne schéma je zakázané
Relačná databáza je zložená z **tabuliek**, ktoré sú definované **relačnou schémou** a obsahujú $n$-tice **relácie**.
**Kľúč** je podmnožina atribútov, ktorých úlohou je jednoznačne **identifikovať** každú $n$-ticu v relácii.
Rozlišujeme nasledovné kľúče:
- **Superkľúč** - každá podmnožina atribútov, ktorá dokáže splniť podmienku kľúča
- **Kandidátsky kľúč** - minimálny superkľúč
- **Primárny kľúč** - jeden zvolený kandidátsky kľúč
- Pokiaľ sa primárny kľúč skladá z viacerých atribútov, nazýva sa **kompozitný**
- **Cudzí kľúč** - množina atribútov, ktorá je superkľúčom v inej relácii
### Dotazovací jazyk SQL a jeho časti (definícia, manipulácia, transakcia)
Ekvivalentom relačnej algebry je jazyk **SQL** (Structured Query Language).
**SQL** (Structured Query Language) je štandardizovaný **ne**procedurálny dotazovací jazyk používaný pre prácu s dátami v relačných databázach.
- Skladá sa z DDL, DML a DCL
- **DDL** (Data Definition Language) - podjazyk pre definíciu dát, slúži na **špecifikáciu relačnej schémy**
- **DML** (Data Manipulation Language) - podjazyk pre manipuláciu s dátami (výber, vkladanie, úpravu a mazanie = **CRUD operácie**)
- **DCL** (Data Control Language) - podjazyk pre riadenie práce s dátami (**správa transakcií**, oprávnenia)
SQL je často dopĺňaný o funkcionalitu v konkrétnych RDBMS - napr. MSSQL Transact-SQL, Oracle PL/SQL, Postgres PL/pgsql. Hovoríme o **dialektoch** SQL.
Príkazy SQL sa skladajú z nasledujúcich komponentov:
- **Príkaz** (statement)
- SELECT, UPDATE, DELETE, ...
- **Dotaz** (query)
- Príkaz, ktorý vracia reláciu
- SELECT
- **Klauzula** (clause)
- Jednotlivé komponenty príkazov alebo dotazov
- WHERE, GROUP BY, ...
- **Predikát** (predicate)
- Podmienka, ktorá obmedzuje účinky príkazu alebo dotazu
- Je vyhodnotená na základe troj-hodnotovej logiky (TRUE, FALSE, NULL)
- Súčasťou predikátu je **operátor**
- =,<,>, <=,>=
- BETWEEN
- LIKE
- IN, NOT IN
- IS, IS NOT
- LIKE
- **Výraz** (expression)
- Konštanta alebo funkcia vracajúca skalárnu hodnotu
- Textové reťazce sa uzatvárajú do jednoduchých uvodzoviek
SQL pracuje s údajmi o **dátových typoch**:
- char - text s pevnou dĺžkou
- varchar - text s premenlivou dĺžkou
- int - celé číslo
- real, float - reálne číslo
- date,time,timestamp - časový údaj
- numeric, decimal - číslo s pevnou dĺžkou celej a desatinnej časti
- uživateľsky definované (napr. Postgres)
## Jazyk definície datového schématu, DDL
**DDL** (Data Definition Language) - podjazyk pre definíciu dát, slúži na **špecifikáciu relačnej schémy**. Príkazy podjazyka DDL **definujú štruktúru relačnej schémy** (a iných objektov).
**Klauzula CREATE TABLE**
- Vytvorí novú relačnú schému (tabuľku) v databáze
- Špecifikuje názvy a typ jednotlivých atribútov
$$
\text{CREATE TABLE}\ r(a\ t, \ldots)
$$
**Klauzula ALTER TABLE**
- Upraví existujúcu tabuľku
- Operácia môže byť **ADD** alebo **DROP**
- Môže upravovať buď integritné obmedzenia **CONSTRAINT** alebo stĺpec **COLUMN**
$$
\text{ALTER TABLE}\ r\ \text{<ADD|DROP>}\ \text{<COLUMN|CONSTRAINT|INDEX>}\ a
$$
**Klauzula DROP TABLE, DROP VIEW**
- Vymaže existujúcu tabuľku, view
$$
\text{DROP TABLE|VIEW}\ r
$$
**Klauzula CREATE VIEW**
- Vytvorí pohľad na dáta - pomenovaný SELECT uložený v databáze, virtuálna tabuľka
- Možnosť vytvoriť materializovaný view - hodnota tabuľky sa vždy prepočíta vopred (pri zmene)
$$
\text{CREATE <MATERIALIZED> VIEW}\ r\ \text{AS SELECT}\ \ldots
$$
**Klauzula CREATE INDEX**
- Vytvorí index nad stĺpcom alebo stĺpcami v tabuľke, vieme určiť explicitne aj typ
- Zvyčajne vieme aj určiť, či má byt kľúč unikátny (UNIQUE) alebo parciálny (WHERE...)
- V Postgres vieme aj určiť typ indexu pomocou **USING** BTREE, HASH, BRIN, GIST...
$$
\text{CREATE <UNIQUE> INDEX}\ idx\ \text{ON}\ r\ (a,b,c\ldots)
$$
## Jazyk manipulácie s dátami, DML
**DML** (Data Manipulation Language) - podjazyk pre manipuláciu s dátami (výber, vkladanie, úpravu a mazanie = **CRUD operácie**). Výsledkom volania DML príkazov je relácia.
- Príkazy sa môžu vnorovať (SELECT FROM (SELECT FROM ...))
- Typicky využívame operátory SOME, ALL, UNIQUE, IN, NOT IN, EXISTS, NOT EXISTS
### CRUD operácie
Klauzula **AS**
- Zodpovedá operácii premenovania $\rho$
- Používa sa v klauzulách SELECT alebo JOIN
- Premenuje danú reláciu
**Klauzula SELECT**
- Zodpovedá operácii projekcie $\Pi$
- Je používaná k vypísaniu požadovaných atribútov relácie uvedené v klauzli **FROM**
- Zodpovedá operácii kartézskeho súčinu $\times$
- Voliteľne je možné pridať predikát **WHERE**
- Zodpovedá operácii selekcie $\sigma$
- Používame matematické operátory, logické operátory, IS NULL, IS NOT NULL, LIKE, ...
- Na konštanty alebo atribúty v klauzuli **SELECT** vieme aplikovať aritmetické operácie
- Na rozdiel od algebry povoluje duplicity
- Ak chceme vynútiť unikátne záznamy, použijeme klauzulu **SELECT DISTINCT**
- Ak nie, použijeme klauzulu **SELECT ALL** (default hodnota, nemusíme písať)
$$
\text{SELECT <DISTINCT|ALL>}\ a\ \text{FROM}\ r\ \text{WHERE}\ x
$$
**Klauzula INSERT**
- Zodpovedá operácii zjednotenie $\cup$
- Vloží záznam do tabuľky
- Zadané hodnoty musia spĺňať podmienky dátového typu a integrity údajov
$$
\text{INSERT INTO}\ r\ \text{VALUES}\ (a,b,c, \ldots)\
$$
**Klauzula UPDATE**
- Zodpovedá operácii výberu $\sigma$ a zjednotenia $\cup$
- Upraví ľubovolný počet záznamov tabuľky
- Nové hodnoty musia spĺňať podmienky dátového typu, integrity údajov
- Voliteľne je možné pridať predikát **WHERE**
$$
\text{UPDATE}\ r\ \text{SET}\ a=b\ \text{<WHERE}\ x \text{>}
$$
**Klauzula DELETE**
- Zodpovedá operácii výberu $\sigma$
- Odstráni ľubovolný počet záznamov tabuľky
- Voliteľne je možné pridať predikát **WHERE**
$$
\text{DELETE FROM}\ r\ \text{<WHERE}\ x \text{>}
$$
### Agregačné funkcie
**Klauzula GROUP BY**
- Zoskupí atribúty tabuľky, následne je možne vybrať len skupiny
- Na skupinách sa môžu aplikovať agregačné funkcie
- Miesto klauzule WHERE sa používa klauzula **HAVING**
- Agregačné funkcie sú:
- COUNT, AVG, SUM, MIN, MAX
- Ak vynecháme GROUP BY, implikuje sa každý atribút
$$
\text{SELECT}\ a\ \text{FROM}\ r\ \text{GROUP BY}\ a\ \text{<HAVING}\ x \text{>}
$$
### Spájanie tabuliek
**Klauzula NATURAL JOIN**
- Zodpovedá operácii natural join $\Join$
- Kombinácia sa robí na základe stĺpcov so spoločným názvom
$$
\text{SELECT}\ a\ \text{FROM}\ r\ \text{NATURAL JOIN}\ s
$$
**Klauzula INNER JOIN**
- Podobné ako NATURAL JOIN, ale musíme špecifikovať cez aké atribúty sa majú tabuľky spojiť klauzulou **ON**
- Duplicitné stĺpce sa premenujú automaticky
$$
\text{SELECT}\ a\ \text{FROM}\ r\ \text{INNER JOIN}\ s\ \text{ON}\ r.c=s.c
$$
**Klauzula OUTER JOIN**
- Zodpovedá operácii OUTER JOIN $⟖$
- V závislosti na strane sa určuje správanie pri hodnotnách NULL - či sa také riadky vynechajú alebo nie
- Môže byť: LEFT, RIGHT, FULL
$$
\text{SELECT}\ a\ \text{FROM}\ r\ \text{<LEFT|RIGHT|FULL>}\ \text{OUTER JOIN}\ s\ \text{ON}\ r.c=s.c
$$
### Ostatné
**Trigger** (spúštač) v databázi špecifikuje činnosti, ktoré sa majú previesť nad databázovou tabuľkou v prípade definovanej udalosti.
- Udalosťou je zvyčajne vloženie alebo zmazanie dát
- Klauzula UPDATE, DELETE, INSERT
- Prípadne ich kombinácia
- Volitelne sa môže špecifikovať podmienka **WHEN**
- Môže byť INSERTING, UPDATING, DELETING
- Procedúru, ktorá sa má spustiť začína klauzulou **BEGIN** a končí **END**
- Ak chceme aby sa vykonala pre každý riadok tabuľky, navyše vložíme klauzulu **FOR EACH ROW**
- Slúžia na zabezpečenie integrity dát v zložitých databázach
- Je to typ uloženej procedúry
$$
\text{CREATE TRIGGER}\ a\ \text{<BEFORE|AFTER|INSTEAD OF>}\ u\ \text{ON}\ r\ \text{WHEN}\ x
$$
**Uložená procedúra** je užívateľom zadefinovaný príkaz alebo dotaz, ktorý je uložený v databáze a je možné ho kedykoľvek zavolať.
- Majú svoje parametre a lokálne premenné (označované zavináčom)
- Voláme ich klauzulou **EXEC**
- Syntax je závislá na konkrétnom jadre databázy
- Výhody: potenciálne zrýchlenie vďaka plánovaniu, zaistenie transakcie, bezpečnosť
$$
\text{CREATE PROCEDURE}\ a\ @p=\ldots\ \text{AS}\ (...)\ \text{GO}
$$
## Relačná algebra, integritné obmedzenia, riadenie transakcií
### Relačná algebra
**Relačná algebra** je formálny dotazovací jazyk.
- Využíva **6 základných operácií**
- Vstupom operácií môže byť jedna alebo viac relácií a **výstupom je vždy jedna relácia**
- To znamená, že operácie sa dajú reťaziť alebo vnárať
**Operácie**:
- **Selekcia** $\sigma_p(r)=\{ t | t \in r \land P(t) \}$
- Výsledkom je relácia, ktorá spĺňa zadaný predikát $P$
- **Projekcia** $\Pi_{A_1...A_n}(R)$
- Výsledkom je relácia vymenovaných $n$ stĺpcov
- Operácia mení relačnú schému výstupnej tabuľky
- Duplicitné riadky sú odstránené
- **Zjednotenie** $r \cup s = \{ t | t \in r \lor t \in s \}$
- Výsledkom je zjednotenie obidvoch relácií
- Musí platiť, že relácie majú rovnakú aritu (počet atribútov) a kompatibilné domény
- **Rozdiel** $r - s = \{ t | t \in r \land t \notin s \}$
- Výsledkom je rozdiel dvoch relácií
- Musí platiť, že relácie majú rovnakú aritu (počet atribútov) a kompatibilné domény
- **Kartézsky súčin** $r \times s = \{ tq | t \in r \land q \in s \}$
- Výsledkom je kartézsky súčin dvoch relácií
- Musí platiť, že atribúty sú disjunktné - ak majú niektoré atribúty rovnaké meno, musia sa premenovať
- **Premenovanie** $\rho_x(r)$
- Vráti reláciu, ktorej meno a názvy stĺpcov sú potenciálne zmenené podľa $x$
- Príklad $\rho_{m(a,b,c,d)}(r)$ - premenuje $r$ na $m$ a stĺpce na $a,b,c,d$
- Musí platiť, že sa vždy vymenujú všetky názvy stĺpcov, aj keď nemeníme ich meno
**Rozšírené operácie**:
- **Zobecnená projekcia**
- Umožňuje používať v zozname projekcie aritmetické funkcie
- **Agregácia** ${}_{G_1...G_n}\ \mathcal{G}_{F_1(A_1)...F_m(A_m)}(r)$
- Aplikuje agregačnú funkciu $F$ na atribút $A$, pričom atribúty sa zoskupia podľa $G$
- Výsledkom je relácia, ktorá obsahuje pre každú skupinu iba jednu hodnotu
- V prípade, že všetky atribúty $G$ sú $null$, zoskupia sa podľa $null$
- Všetky operácie okrem $count$ vracajú na $null$ číslo $0$
- Agregačné funkcie: avg, min, max, sum, count
### Spojovanie relácií
Relácie spájame pomocou tzv. JOINov (spojení).
- JOIN zjednocuje $n$-tice relácií na základe prieniku hodnôt atribútov
Rozlišujeme druhy JOINov:
- **Natural join** $r \Join s$
- $n$-tice sa zjednotia na základe rovnako pomenovaných atribútov
- Príklad pre $R=(A,B,C,D)$ a $S=(E,B,D)$
- $R \Join S = (A,B,C,D,E)$
- $R \Join S = \Pi_{r.A,r.B,r.C,r.D,s.E}(\sigma_{r.B=s.B \land r.D =s.D}(r \times s))$
- **Outer join**
- Rozšírenie operácie Natural join
- Zabraňuje strate informácií tak, že pridá do výslednej relácie aj $n$-tice ktoré nepatria do spoločného prieniku
- Hodnoty nahradí za $null$
- Môže byť: Left $⟕$, Right $⟖$, Full $⟗$
### Integritné obmedzenia
**Integritné obmedzenie** chráni databázu voči náhodnému poškodeniu.
- Zabezpečujú, že oprávnené zmeny v databáze nevedú k stráte **konzistencie dát**
Zoznam integritných obmedzení:
- NOT NULL - atribút nemôže mať hodnotu NULL
- UNIQUE - každá hodnota atribútu musí byť unikátna
- PRIMARY KEY - definuje primárny kľúč tabuľky
- FOREIGN KEY - zaistí, aby hodnota zodpovedala hodnote kľúča v inej tabuľke
- Zabezpečuje referenčnú integritu
- CHECK - každá hodnota sa skontroluje zadanou podmienkou
- DEFAULT - implicitná hodnota atribútu
- INDEX - pomáha urýchliť databázu, ak často podľa hodnoty vyhľadávame
Príklad (MSSQL T-SQL):
```tsql
CREATE TABLE person (
p_id int NOT NULL PRIMARY KEY,
op char(10) UNIQUE NOT NULL,
name varchar(255) NOT NULL,
species varchar(255) DEFAULT ‘human’,
j_id int FOREIGN KEY REFERENCES job_table (j_id),
CHECK (p_id > 0)
)
```
Integritu vieme obmedziť aj definovaním vlastného dátového typu pomocou **CREATE DOMAIN**.
### Riadenie transakcií
**Transakcia** je postupnosť operácií (DML príkazov), ktoré prevedú dátovú schému z jedného konzistentného stavu do druhého.
- Transakcia pracuje s databázou vždy v konzistentnom stave
- Počas vykonávania transakcie sa môže databáza dostať do nekonzistentného stavu ale na konci jej vyhodnotenia platí, že v konzistentnom stave zostane
Transakcia sa riadi pravidlami **ACID**:
- **A**tomicity - príkazy nad DB sa vykonajú všetky úspešne, alebo sa nevykonajú žiadne (COMMIT/ROLLBACK)
- **C**onsistency - po vykonaní príkazov sa neporušia žiadne integritné obmedzenia
- **I**solation - transakcie sú navzájom izolované, zvyčajne určujeme izolačné úrovne podľa potreby
- **D**urability - uložené dáta sa budú dať znova načítať v konzistentnom stave, aj po výskytu chyby (napr. výpadok elektriky, crash) - zvyčajne zaručené uložením na disk
Transakcia sa môže dostať do nasledujúcich **stavov**:
- **Aktívna** (Active)
- Transakcia je v tomto stave na začiatku vyhodnotenia
- Pokiaľ beží, tak v tomto stave zostáva
- **Čiastočne potvrdená** (Partially commited)
- Akonáhle bola vykonaná posledná operácia transakcie
- **Chybujúca** (Failed)
- Po zistení, že beh transakcie nemôže pokračovať
- **Zrušená** (Aborted)
- Potom, čo bola transakcia zrušená a databáza bola vrátená do pôvodného stavu
- **Potvrdená** (Commited)
- Po úspešnom dokončení
Transakcie vieme izolovať v rôznych **úrovniach izolácie**:
- **Read Uncommited**
- Najtolerantnejšia úroveň
- Transakcia vidí zmeny ostatných transakcií okamžite
- Môže nastať problém čítania SELECT nepotvrdených (uncommited) údajov - **dirty read**
- Dva po sebe volané dotazy SELECT vrátia rôzne výsledky - **problém neopakovateľného čítania** (non-repeatable read)
- Po opakovam volaní SELECT nám pribúdaj/miznú riadky - **fantómové dáta** (phantom data)
- **Read Commited**
- Transakcia vidí dáta zmenené konkurentnou transakciou až po potvrdení (commited transaction)
- Rieši problém s **dirty read**s
- **Repeatable Read**
- Je zaručené, že v priebehu transakcie nemôže dojsť k problému neopakovateľného čítania
- Rieši **non-repeatable read**
- **Serializable**
- Najvyššia úroveň zabezpečenia izolácie transakcií
- Pokiaľ sa detekuje, že iná konkurentná transakcia je nad objektom (row, column, table) už potvrdená (commited), zruší sa (rollback)
- Transakcie teda bežia v podstate jedna po druhej (serialized)
- Opravuje **problém fantómov**, ale zamedzuje urýchlovacie triky (read-locking, write-locking, snapshotting)
Vlastnosti transakcií atomickosti (Atomic) a trvanlivosti (Durability) sú implementované pomocou **tieňovej databázy** (shadowing).
- Transakcia sa vykonáva na tieňovej verzii
- V prípade chyby sa tieňová vymaže, inak sa stane tou skutočnou
Transakcie sa môžu spracovávať **paralelne** (súbežne).
- Databáza vytvára pre súbežné transakcie **plán** (schedule) ich spracovania, ktorý musí byť serializovateľný
- Plán môže byť conflict alebo view serializable
- Conflict serializable - kontroluje sa graf závislostí čítaní a zápisov, ak existuje sériový plán volania transakcií (neexistuje cyklus), tak máme garantované, že po vykonaní akéhokoľvek sériového plánu budú dáta v konzistentnom stave a s minimálnym lockovaním objektov databázy (vysoká priepustnosť operácií)
- View serializable - relaxuje podmienku cyklov v conflict serializable pláne, kontroluje sa iba poradie read-write operácií na začiatku, počas behu, a na konci transakcií
- V plánoch nás zaujímajú iba operácie čítania a zápisu
- Paralelný výpočet je rýchlejší, ale môže dojsť k problémom ako napr. deadlock (cyklická závislosť)
## Indexovanie a hashovanie
### Indexovanie
**Indexovanie** je proces, vďaka ktorému zrýchlime prístup k údajom za cenu spomalenia operácií vkladania či odstránenia, ktoré menia dáta indexovaných sĺpcov. Algoritmicky redukujeme počet sekvenčných alebo náhodných prístupov na diskové médium.
- Indexovaný stĺpec má priradenú **indexovaciu tabuľku** - zvyčajne omnoho menšiu než súbor celej tabuľky
- Indexy môžu byť buď **zoradené** (ordered) alebo **hashované** (hashed)
### Zoradené indexy (ordered index)
- Indexové záznamy sú uložené podľa vyhľadávacieho kľúča
- **Primárny index** (primary index) - zoradený sekvenčný súbor
- Vyhľadávací kľúč určuje poradie záznamu v súbore
- Nazývaný aj ako zhlukujúci index (clustering index) - sú podľa neho fyzicky zoradené súbory na disku a môže byť iba jeden v tabuľke
- Nemusí byť vo všetkých prípadoch primárnym kľúčom
- Môže byť hustý (dense) a riedky (sparse)
- **Sekundárny index** (secondary index)
- Vyhľadávací kľúč určuje iné poradie než v zoradenom sekvenčnom súbore
- Nazývaný nezhlukujúci index (non-clustering index)
- Môže byť iba hustý (dense)
Index je **hustý (dense)** práve vtedy, ak existuje indexový záznam pre každú hodnotu v tabuľke.
- Rovnaké hodnoty sa v indexe neopakujú
- Má za následok veľký overhead pri INSERT a DELETE operáciách
- Na druhú stranu je rýchlejší pri operáciách JOIN, WHERE oproti sparse index
Index je **riedky (sparse)** práve vtedy, ak indexový záznam existuje iba pre niektoré hodnoty v tabuľke.
- Musíme najprv nájsť najbližší indexový záznam k našej vyhľadávanej položke
- Následne musíme prechádzať tabuľku sekvenčne
- Zvyčajne pomalší ako dense index ale zaberá menej miesta na disku (ale viacej v RAM)
**Viacúrovňový index (hierarchical index)** používame vtedy, ak sa primárny index nevojde do operačnej pamäte RAM.
- Z primárneho indexu sa spraví niekoľko riedkych (sparse) indexov
- Proces opakujeme ľubovolne-krát
Najpoužívanejšou indexovou štruktúrou v databázach sú **B+ stromy**.
- Jedná sa o viacúrovňový index (hierarchical index) v tvare vyváženého $n$-árneho stromu
Samotné dáta sa ukladajú rôznym spôsobom - napr. v Postgres sú to 8KB stránkovacie súbory, ktoré sú indexované zvoleným indexom.
### Hashované indexy (hash index)
Pri **hashovanom indexe** získavame **kyblíky** (buckets), do ktorých spadajú vyhľadávacie kľúče.
- Sú neefektívne pri vyhľadávaní rozsahov (WHERE a.x BIGGER, LESS THAN b.y)
- Rozlišujeme dynamické a statické hashovanie
- Dynamické umožňuje dynamicky meniť svoju hashovaciu funkciu podľa potrieb velkosti databázy
- Vzniká problém pretečenia kyblíkov (overflow) a kolízií (collisions)
- Riešené cez overflow chaining - closed hashing
**Hashovacia funkcia** je funkcia, ktorá prevádza množinu vyhľadávacích kľúčov na množinu adries jednotlivých kyblíkov.
- Používa sa ako pri vyhľadávaní, tak aj pri pridávaní a mazaní záznamov
- Ideálna hashovacia funkcia je rovnomerná, každý kýblik ma rovnaký počet priradených záznamov
- Snažíme sa minimalizovať možnosť kolízií (slabá, silná bezkolíznosť)
### Využitie pri JOIN operáciách
Indexovanie sa používa pri operáciách:
- Indexed nested-loop join
- Každej $n$-tici nájde druhú pomocou indexu
- Na rozdiel od naivného nested loop joinu nám zlepšuje zložitosť na $O(|R|log|S|)$
- Vhodné aj pre non-equi joins (ON a = b WHERE a.x BIGGER, LESS THAN b.y)
- Merge join
- Relácie sa zoradia podľa indexov a potom sa spoja
- Používa sa na equi-join - podmienky WHERE a = b
Hashovanie sa využíva pri operácii Hash join.
- $n$-tice sa navzájom porovnávajú pomocou obsahu kyblíkov
- Vhodné pre JOIN veľkých tabuliek, dobrá zložitosť $O(R+S)$ ale veľký overhead (najmä RAM)
- Dá sa paralelizovať
- Nevyžaduje indexy na porovnávaných stĺpcoch