Files
knowledge-base/DATABASES.md
Stanislav Hubacek c6fa0bff6a commit
2026-06-11 15:27:28 +02:00

17 KiB

🗄️ Databázová architektura

Klasifikace databází

Relační (SQL)

DB Licence Use case
PostgreSQL Open source Univerzální, geospatial, analytika
MySQL Open source Web, LAMP stack
MariaDB Open source MySQL kompatibilní
Microsoft SQL Server Proprietary Enterprise .NET
Oracle DB Proprietary Enterprise
Amazon Aurora Managed MySQL/PostgreSQL kompatibilní

NoSQL

Typ DB Use case
Document MongoDB, Couchbase JSON data, flexibilní schema
Key-Value Redis, DynamoDB Cache, session store, real-time
Wide-column Cassandra, ScyllaDB Time-series, IoT, velká data
Graph Neo4j, Dgraph Vztahy, doporučení, social grafy

Transaction isolation levels

Úroveň Dirty Read Non-repeatable Read Phantom Read Serialization Anomaly
Read Uncommitted Ano (možné) Ano Ano Ano
Read Committed Ne (prevence) Ano Ano Ano
Repeatable Read Ne Ne Ano (PostgreSQL: Ne) Ano
Serializable Ne Ne Ne Ne

Anomálie:

  • Dirty Read — čtení dat z necommitnuté transakce (data mohou být rollbacknuta)
  • Non-repeatable Read — stejný dotaz vrátí jiná data (jiná transakce mezitím updatovala řádek)
  • Phantom Read — stejný dotaz vrátí nové řádky (jiná transakce insertla data splňující podmínku)
  • Serialization Anomaly — výsledek transakcí není ekvivalentní žádnému sériovému pořadí

PostgreSQL specific

  • Read Uncommitted se chová jako Read Committed (není implementováno)
  • Repeatable Read v PG je Snapshot Isolation — zabraňuje i phantom reads
  • Serializable v PG používá Serializable Snapshot Isolation (SSI) — detekce sériových konfliktů

PostgreSQL detail

MVCC (Multi-Version Concurrency Control)

  • Každá transakce vidí snapshot dat (transaction snapshot) z okamžiku startu
  • Staré verze řádků (tuple) zůstávají v tabulce, označené jako xmax / xmin
  • INSERT vytvoří nový tuple s xmin = current_xid
  • DELETE označí tuple xmax = current_xid (nezmizí hned)
  • UPDATE = DELETE old + INSERT new
  • VACUUM fyzicky maže tuple starší než nejstarší aktivní snapshot

VACUUM a autovacuum

Parametr Popis Výchozí
autovacuum_vacuum_threshold Min. mrtvých řádků pro spuštění 50
autovacuum_vacuum_scale_factor % z tabulky jako threshold 0.2 (20 %)
autovacuum_analyze_threshold Min. změněných řádků pro ANALYZE 50
autovacuum_vacuum_cost_limit Limituje I/O vacuum (prevence zátěže) 200
autovacuum_naptime Interval mezi kontrolami 1 min
deadlock_timeout Detekce deadlocků 1 s

Příznaky nedostatečného vacuum:

  • Růst tabulky (bloat) — staré tuple zabírají místo
  • Zhoršení výkonu index scanů (VISIBLE MAP není aktuální)
  • XID wraparound hazard — emergency vacuum (může zastavit DB)

WAL archiving a PITR

# postgresql.conf
wal_level = replica                 # nebo logical
archive_mode = on
archive_command = 'aws s3 cp %p s3://backups/pg-wal/%f'
  • WAL (Write-Ahead Log) — append-only log všech změn
  • WAL archiving — kontinuální záloha WAL segmentů (16 MB)
  • PITR (Point-In-Time Recovery) — obnova k libovolnému okamžiku
    1. Restore base backup (pg_basebackup)
    2. Replay WAL archivů až k cílovému času
    3. recovery_target_time = '2026-06-03 10:30:00 UTC'

Replication slots

  • Physical replication slot — zaručuje, že WAL není smazán masterem, dokud ho replica nespotřebuje
  • Logical replication slot — pro logickou replikaci (selectivní tabulky, transformace dat)
  • Riziko: pokud replica spadne a slot není aktivní, WAL naroste na disku (disk full)
  • Monitoring: pg_replication_slots, pg_stat_replication

Replikace

Typ Popis Latence
Synchronní Zápis potvrzen až po replikaci na všechny nod Vysoká, ale konzistentní
Asynchronní Zápis potvrzen ihned, replikace na pozadí Nízká, možný data loss
Semi-synchronní Potvrzení od majority nodů Kompromis

Topologie

  • Leader-Follower (Master-Slave) — čtení z replic
  • Leader-Leader (Multi-master) — zápis na více nodů
  • Quorum-based — R + W > N (Cassandra, DynamoDB)

Index types

Typ Algoritmus Use case Operace Poznámka
B-tree Balanced tree Většina dotazů — =, <, >, BETWEEN, IN, LIKE (prefix) Rychlé vyhledávání, řazení Výchozí v PostgreSQL, MySQL
Hash Hash table Pouze = (equality) Rychlé lookup Malá velikost, nelze range dotazy
GiST Generalized Search Tree Full-text, geometrie, intervaly, IP rozsahy Rychlé: overlaps, contains, distance GIST pro geometrii (PostGIS), full-text
GIN (Generalized Inverted Index) Inverted index Pole, JSONB, full-text search contains (@>), overlaps (&&) Pomalý build, rychlé čtení
BRIN (Block Range Index) Min/Max per block range Velké tabulky, data v pořadí (time-series) Range dotazy na korelovaná data Extrémně malý (tisíckrát menší než B-tree)
SP-GiST Space-partitioned GiST Quad-tree, KD-tree, radix tree Partitioned search Geografické clustery, síťová data

Index selection guide

Query pattern Doporučený index Příklad
WHERE user_id = 123 B-tree na user_id Uživatelský lookup
WHERE status = 'active' AND created_at > '2026-01-01' Composite B-tree na (status, created_at) Filtrace + range
WHERE data @> '{"key": "value"}' GIN na JSONB sloupec JSONB dotazy
WHERE tags && ARRAY['urgent'] GIN na pole Tagy
WHERE position <@> POINT(50, 14) < 1000 GiST na geometry Lokalitní dotazy
WHERE event_time BETWEEN '2026-06-01' AND '2026-06-02' BRIN na event_time Time-series, logy
WHERE email = 'user@example.com' Hash na email Equality only

Query execution

Seq scan vs Index scan vs Bitmap scan

Typ Popis Kdy se používá
Seq Scan Prochází všechny řádky tabulky Velká část tabulky (>10 %), malá tabulka, žádný vhodný index
Index Scan Hledá v indexu, pak náhodný přístup k heap Malá podmnožina dat (<5 %), selektivní dotazy
Index Only Scan Načítá data pouze z indexu (ne z heap) Všechny potřebné sloupce jsou v indexu (covering index)
Bitmap Scan Kombinace více indexů → bitmapa → heap access AND/OR podmínky na více indexovaných sloupcích
Bitmap Heap Scan Načítá řádky z bitmapy (srovnané) AND/OR kombinace, ~5-20 % tabulky

EXPLAIN ANALYZE

EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT * FROM orders WHERE user_id = 456 AND created_at > '2026-01-01';

-- Výstup:
-- Index Scan using idx_orders_user_created on orders
--   Index Cond: ((user_id = 456) AND (created_at > '2026-01-01'::date))
--   Buffers: shared hit=3
--   Planning Time: 0.12 ms
--   Execution Time: 0.34 ms

Klíčové metriky: Execution Time, Planning Time, Buffers (hit/read/dirtied), Rows Removed by Filter, Actual Time (first...last)

Sharding

Distribuce dat napříč uzly podle shard klíče.

                    ┌─────────┐
                    │  Proxy  │
                    │  Router │
                    └────┬────┘
              ┌──────────┼──────────┐
         ┌────▼───┐ ┌───▼────┐ ┌───▼────┐
         │Shard A │ │Shard B │ │Shard C │
         │ 0-100  │ │101-200 │ │201-300 │
         └────────┘ └────────┘ └────────┘

Hash-based sharding

shard_id = hash(shard_key) % number_of_shards

Range-based sharding

  • Data rozdělena podle rozsahu hodnot (např. uživatelé A-M, N-Z)
  • Může vést k nerovnoměrnému rozdělení (hot spots)

Consistent hashing

Hash ring:
   0 ─── shard A ─── hash(key1)
         │
   90 ─── shard B ─── hash(key2)
         │
  180 ─── shard C ─── hash(key3)
         │
  270 ─── shard D ─── hash(key4)
  • Minimalizuje přeuspořádání přidáním/odebráním nodu (pouze sousední shard)
  • Virtual nodes (vnodes) — každý fyzický nod má více virtuálních bodů na ring (lepší distribuce)
  • Koordinační služba: Cassandra (vnodes), Riak (vnodes), DynamoDB (Consistent Hashing)

Rebalancing

  • Ruční — zastavit zápisy, přerozdělit data, restartovat
  • Automatické — incremental migration (Cassandra vnodes)
  • Proxy-based — Vitess (shard splitting), Citus (shard rebalancing)

Routing approaches

  • Proxy-based — aplikace jde na proxy, ta routuje (Vitess, ProxySQL)
  • Client-side — aplikace ví, na který shard jít
  • DNS-based — každý shard má vlastní endpoint

CAP teorém

V distribuovaném systému lze mít pouze 2 ze 3:

  • Consistency — všichni vidí stejná data
  • Availability — každý request dostane odpověď
  • Partition tolerance — systém funguje i přes výpadek komunikace

V praxi: P je vždy vyžadováno, volíme mezi CP (konzistence) a AP (dostupnost).

PACELC rozšíření

PACELC rozšiřuje CAP o chování za normálních podmínek (bez partition):

  • Partition → Availability vs Consistency
  • Else (bez partition) → Latency vs Consistency
DB Partition volba Else volba
Cassandra AP (dostupnost) LC (nízká latence, eventual consistency)
DynamoDB (default) AP LC
MongoDB CP (primární) LC
PostgreSQL (single) CP CC
CockroachDB CP CC

Quorum detail

  • R (read quorum) + W (write quorum) > N (replication factor)
  • Typické: N=3, R=2, W=2 (toleruje 1 node down)
  • Sloppy quorum — při nedostupnosti nodu, data dočasně uložena na jiném nodu (nastolit konzistenci po obnově)
  • Hinted handoff — dočasný zápis na jiný node s hintem, při obnově se data přenesou

Caching

Vrstva Nástroj Use case
Application cache Redis, Memcached Session, API response cache
Database cache Built-in Query cache, buffer pool
CDN cache CloudFront, Fastly Static assets, API responses
HTTP cache Varnish, nginx Reverse proxy cache, ESI

Cache strategie

Strategie Popis Use case
Cache-aside Aplikace načte z cache, při miss jde do DB a naplní cache Obecná
Read-through Cache sama načte z DB při miss Jednoduché lookupy
Write-through Zápis jde do cache i DB zároveň Konzistence
Write-behind Zápis do cache okamžitě, do DB asynchronně Propustnost
Cache-aside (lazy loading) TTL + invalidace Nejčastější

Redis detail

Data structures:

Struktura Popis Use case
String Binární string (max 512 MB) Cache hodnoty, session tokeny, counters
Hash Map field-value Uživatelský profil, objekt v cache
List Linked list (push/pop na oba konce) Queue (RPUSH/LPOP), log stream
Set Unikátní hodnoty (unordered) Tags, deduplikace, memberships
Sorted Set Unikátní + score (řazení) Leaderboardy, rate limiting, timeouts
Bitmap Bitové pole Feature flagy, daily active users
HyperLogLog Approximate cardinality (12 KB = 2^64) Unikátní návštěvníci (error < 1%)
Stream Append-only log (Kafka-like) Event store, messaging

Eviction policies:

Policy Popis Use case
noeviction Chyba při zápisu když je plno Transakční data, neztrácet
allkeys-lru LRU na všechny klíče Obecná cache, standard
allkeys-lfu LFU na všechny klíče Často přistupovaná data
volatile-lru LRU na klíče s TTL Cache s expirací
volatile-ttl Nejblíž k expiraci Krátkodobá data
allkeys-random Náhodný Testování

Redis Cluster vs Sentinel:

Vlastnost Redis Sentinel Redis Cluster
Škálování Read replicas (master + replica) Data sharding (16384 hash slotů)
Auto-failover Ano (Sentinel) Ano (gossip-based)
Multi-key ops Ano (transactiony na masteru) Omezené (stejný hash slot)
Client komunikace Přes Sentinel (deprecated) Cluster nodes redirect (MOVED/ASK)
Minimální uzly Master + Replica + 3 Sentinel 3 masters (každý s replikou)
Use case Vysoká dostupnost, single shard Multi-shard, horizontální škálování

Connection pooling

Pooler DB Typ Protokol
PgBouncer PostgreSQL Proxy (transaction/session) PostgreSQL wire
RDS Proxy PostgreSQL, MySQL Managed proxy AWS
ProxySQL MySQL Proxy (advanced routing) MySQL wire
Odyssey PostgreSQL Proxy (multithreaded) PostgreSQL wire
pgpool-II PostgreSQL Proxy (replication, load balancing) PostgreSQL wire

PgBouncer režimy:

  • Session pooling — spojení drženo po celou dobu session (aplikace) → overhead
  • Transaction pooling — spojení vráceno po dokončení transakce → efektivnější (vyžaduje bezstavovost)

Migrace dat

Schéma migrace (PostgreSQL / MySQL)

V1__initial_schema.sql
V2__add_users_table.sql
V3__add_email_index.sql
V4__add_orders_table.sql

Zero-downtime migrace

  1. Expand — přidání nového sloupce/tabulky (aplikace toleruje oba stavy)
  2. Migrate — backfill dat, update aplikace na nové schema
  3. Contract — odstranění starého sloupce/tabulky

Nástroje detail

Nástroj Jazyk Strategie Zero-downtime Rollback
Flyway Java (multi-lang CLI) Versioned SQL Omezeně (jen additive) undo (limited, enterprise)
Liquibase Java (multi-lang CLI) Changesets (XML/YAML/JSON/SQL) Ano (changeset design) rollback <count>
Alembic Python Auto-generation, versioned Ano (branching) downgrade
Prisma Migrate TypeScript Declarative schema → diff Ano (shadow DB) migrate diff
gh-ost Go Triggerless online DDL (MySQL) Ano (binlog stream) Ne (progresivní)
pgroll Go Online schema migrace (PG) Ano (views, multiple versions) Ano (okamžitý)

Data consistency patterns

Pattern Popis Příklad
Strong consistency Po zápisu každý read vidí nejnovější data Single DB, Raft, Spanner
Eventual consistency Po zápisu se data časem propagují DNS, DynamoDB (default), Cassandra
Read-after-write Autor svůj zápis vždy vidí (ostatní eventual) Sociální sítě, komentáře
Causal consistency Kauzálně závislé operace viděny ve správném pořadí COPS, Orbe, MongoDB (causal clusters)
Monotonic reads Nevidíte starší data po tom, co jste viděli novější Cassandra (MONOTONIC_READ consistency)
Monotonic writes Zápisy od jednoho clienta v pořadí Queue-based, single leader

Storage engines — přehled

B-Tree vs LSM-Tree

Vlastnost B-Tree LSM-Tree
Zápis In-place update (náhodný I/O) Append-only (sekvenční I/O)
Čtení Rychlé (přímo v page) Pomalejší (merge z více SSTable)
Kompaktnost Horší (page fragmentation) Lepší (kompaktní SSTable)
Write amplification Nižší Vyšší (kompakce)
Read amplification Nižší Vyšší (bloom filtry pomáhají)
Typické DB PostgreSQL, MySQL (InnoDB) Cassandra, RocksDB, LevelDB

Write-Ahead Log (WAL)

  • Append-only log pro crash recovery
  • Každá změna se zapíše do WAL před aplikací na data page
  • Checkpoint = bod, od kterého je WAL při recovery potřeba

MVCC (Multi-Version Concurrency Control)

  • Každá transakce vidí snapshot dat v okamžiku startu
  • Staré verze řádků zůstávají v tabulce (vacuum/GC)
  • Izolační úrovně: Read Committed, Repeatable Read, Serializable

Best practices

  • Connection pooling — PgBouncer, RDS Proxy, ProxySQL
  • Indexování podle query patternů — nemít zbytečné indexy
  • Read replicas pro reporting a analytiku
  • Backup & recovery — point-in-time recovery (PITR), pravidelné testy
  • Query monitoring — slow query log, pg_stat_statements, performance_schema
  • Encryption at rest & in transit
  • Migrace v CI/CD — součást pipeline, ne manuálně

Zdroje

Odkazy, knihy a standardy: sources/databases/sources.md