Вступ до баз даних

База даних — організоване сховище для зберігання, керування та отримання даних. Замість тисяч файлів — структурована система з швидким пошуком та надійністю.

Навіщо потрібна база даних?

┌─────────────────────────────────────────────────────────────────┐
│                     БЕЗ БАЗИ ДАНИХ                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   users.json                                                    │
│   ├── Один файл = один user                                    │
│   ├── Пошук = прочитати всі файли                              │
│   ├── Конкурентний доступ = колізії                            │
│   └── Зв'язки між даними = складно                             │
│                                                                 │
│   Проблеми:                                                     │
│   ✗ Повільний пошук (O(n))                                     │
│   ✗ Немає транзакцій                                           │
│   ✗ Легко втратити дані                                        │
│   ✗ Важко масштабувати                                         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                      З БАЗОЮ ДАНИХ                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   PostgreSQL                                                    │
│   ├── Структуровані таблиці                                    │
│   ├── Індекси для швидкого пошуку                              │
│   ├── Транзакції — атомарність операцій                        │
│   └── Зв'язки через JOIN                                       │
│                                                                 │
│   Переваги:                                                     │
│   ✓ Швидкий пошук (O(log n) з індексами)                       │
│   ✓ ACID гарантії                                              │
│   ✓ Резервне копіювання                                        │
│   ✓ Масштабування                                              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

SQL vs NoSQL

SQL (реляційні бази даних)

Дані організовані в таблиці з рядками та колонками. Є чітка схема (структура даних).

┌────────────────────────────────────────────────────────────────┐
                      ТАБЛИЦЯ users                             
├──────┬──────────────┬─────────────────────┬────────────────────┤
  id      name             email             created_at      
├──────┼──────────────┼─────────────────────┼────────────────────┤
  1     Олександр     alex@example.com     2026-01-15 10:00  
  2     Марія         maria@example.com    2026-01-16 14:30  
  3     Петро         petro@example.com    2026-01-17 09:15  
└──────┴──────────────┴─────────────────────┴────────────────────┘
                              
                               JOIN
                              
┌────────────────────────────────────────────────────────────────┐
                      ТАБЛИЦЯ orders                            
├──────┬───────────┬─────────────┬───────────┬──────────────────┤
  id    user_id     product      price       order_date    
├──────┼───────────┼─────────────┼───────────┼──────────────────┤
  1        1        Laptop       25000      2026-01-16     
  2        1        Mouse          500      2026-01-16     
  3        2        Keyboard      1200      2026-01-17     
└──────┴───────────┴─────────────┴───────────┴──────────────────┘

Приклади SQL баз:
- PostgreSQL — найпотужніша, рекомендована
- MySQL/MariaDB — популярна для веб
- SQLite — вбудована, для простих застосунків

NoSQL (нереляційні бази даних)

Гнучка структура, без жорсткої схеми.

┌────────────────────────────────────────────────────────────────┐
                    ДОКУМЕНТ (MongoDB)                          
├────────────────────────────────────────────────────────────────┤
  {                                                             
    "_id": "user_001",                                          
    "name": "Олександр",                                        
    "email": "alex@example.com",                                
    "orders": [
│      { "product": "Laptop", "price": 25000 },                  │
│      { "product": "Mouse", "price": 500 }                      │
],                                                          
    "preferences": {                                            
      "theme": "dark",                                          
      "language": "uk"                                          
    }                                                           
  }                                                             
└────────────────────────────────────────────────────────────────┘

Типи NoSQL:

Тип Опис Приклад
Document JSON-подібні документи MongoDB
Key-Value Простий ключ → значення Redis
Column Колонкове сховище Cassandra
Graph Зв'язки між даними Neo4j

Коли що використовувати?

┌────────────────────────────────────────────────────────────────┐
│                    ВИБІР БАЗИ ДАНИХ                            │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  SQL (PostgreSQL) — коли:                                      │
│  ✓ Структуровані дані                                         │
│  ✓ Складні запити та JOIN                                     │
│  ✓ Потрібні транзакції (гроші, замовлення)                    │
│  ✓ Цілісність даних критична                                  │
│                                                                │
│  Приклади: користувачі, замовлення, фінанси, інвентар         │
│                                                                │
│  ─────────────────────────────────────────────────────────────│
│                                                                │
│  NoSQL (MongoDB) — коли:                                       │
│  ✓ Гнучка/змінна схема                                        │
│  ✓ Ієрархічні дані (вкладені документи)                       │
│  ✓ Швидке прототипування                                      │
│  ✓ Горизонтальне масштабування                                │
│                                                                │
│  Приклади: логи, контент CMS, каталоги товарів, IoT дані      │
│                                                                │
│  ─────────────────────────────────────────────────────────────│
│                                                                │
│  Redis (Key-Value) — коли:                                     │
│  ✓ Кешування                                                  │
│  ✓ Сесії користувачів                                         │
│  ✓ Черги повідомлень                                          │
│  ✓ Real-time лічильники                                       │
│                                                                │
│  Приклади: кеш, rate limiting, pub/sub                        │
│                                                                │
└────────────────────────────────────────────────────────────────┘

Порівняльна таблиця

Критерій PostgreSQL MongoDB Redis
Тип SQL Document Key-Value
Схема Строга Гнучка Немає
Транзакції ACID Базові Обмежені
Масштабування Вертикальне Горизонтальне Горизонтальне
Швидкість запису Середня Висока Дуже висока
Складні запити Відмінно Добре Немає
Зберігання На диску На диску В RAM

ACID принципи

ACID — гарантії для транзакцій в SQL базах даних:

┌────────────────────────────────────────────────────────────────┐
                         ACID                                   
├────────────────────────────────────────────────────────────────┤
                                                                
  A  Atomicity (Атомарність)                                  
      Транзакція або виконується повністю, або не виконується  
      зовсім. Немає "наполовину виконаних" операцій.           
                                                                
      Переказ грошей:                                          
      1. Зняти з рахунку А                                     
      2. Додати на рахунок Б                                   
       Або обидві операції, або жодна!                        
                                                                
  ─────────────────────────────────────────────────────────────│
                                                                
  C  Consistency (Узгодженість)                               
      База завжди в коректному стані.                          
      Всі обмеження (constraints) дотримуються.                
                                                                
      email має бути унікальним  база не дозволить            
      два однакових email                                      
                                                                
  ─────────────────────────────────────────────────────────────│
                                                                
  I  Isolation (Ізоляція)                                     
      Паралельні транзакції не заважають одна одній.           
                                                                
      Два користувачі редагують різні рядки                   
      кожен бачить консистентні дані                           
                                                                
  ─────────────────────────────────────────────────────────────│
                                                                
  D  Durability (Довговічність)                               
      Збережені дані не втрачаються навіть при збоях.          
                                                                
      COMMIT пройшов  дані записані на диск,                  
      навіть якщо сервер впаде                                 
                                                                
└────────────────────────────────────────────────────────────────┘

Приклад транзакції

-- Переказ грошей: атомарна операція
BEGIN;

UPDATE accounts SET balance = balance - 1000 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE user_id = 2;

-- Якщо все OK
COMMIT;

-- Якщо щось пішло не так
-- ROLLBACK;

ORM — що це?

ORM (Object-Relational Mapping) — бібліотека, що дозволяє працювати з базою через об'єкти замість SQL.

# Без ORM (чистий SQL)
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
row = cursor.fetchone()
user = {"id": row[0], "name": row[1], "email": row[2]}

# З ORM (SQLAlchemy)
user = session.query(User).filter(User.id == user_id).first()
print(user.name)  # Працюємо як з об'єктом

Популярні ORM

Мова ORM
Python SQLAlchemy, Django ORM
JavaScript Prisma, Sequelize, TypeORM
Go GORM, sqlx
Ruby ActiveRecord
PHP Eloquent (Laravel)

Плюси і мінуси ORM

✓ Простіший код
✓ Захист від SQL injection
✓ Переносимість між БД
✓ Міграції схеми

✗ Складні запити важче оптимізувати
✗ N+1 проблема
✗ Додатковий шар абстракції

Індекси

Індекс — структура даних для швидкого пошуку. Як індекс в книзі — замість гортати всі сторінки, дивишся на потрібну літеру.

┌────────────────────────────────────────────────────────────────┐
                      БЕЗ ІНДЕКСУ                               
├────────────────────────────────────────────────────────────────┤
                                                                
  SELECT * FROM users WHERE email = 'alex@example.com'         
                                                                
  Сканування всієї таблиці (Full Table Scan):                  
  [row 1]  [row 2]  [row 3]  ...  [row 1000000]           
                                                                
  Час: O(n)  лінійно залежить від кількості рядків            
                                                                
└────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────┐
                       З ІНДЕКСОМ                               
├────────────────────────────────────────────────────────────────┤
                                                                
  CREATE INDEX idx_users_email ON users(email);                
                                                                
  Пошук по B-tree індексу:                                      
              [M]                                               
            /     \                                             
         [D]       [S]                                          
        /   \     /   \                                         
      [A]  [G]  [N]   [Z]                                       
                                                               
     alex@...   Знайшли за 3 кроки!                           
                                                                
  Час: O(log n)  логарифмічно                                 
                                                                
└────────────────────────────────────────────────────────────────┘

Коли створювати індекси?

✓ Колонки в WHERE
✓ Колонки в JOIN
✓ Колонки в ORDER BY
✓ Унікальні значення (email, username)

✗ Не створювати на все поспіль
✗ Індекси займають місце
✗ Індекси уповільнюють INSERT/UPDATE

Практичний приклад: вибір БД

Веб-застосунок (типовий)

PostgreSQL — основна база
├── users (id, email, password_hash, created_at)
├── posts (id, user_id, content, created_at)
├── comments (id, post_id, user_id, content)
└── ...

Redis — кешування та сесії
├── session:abc123 → {user_id: 1, ...}
├── cache:posts:recent → [post1, post2, ...]
└── rate_limit:user:1 → 45

Docker Compose

services:
  app:
    image: myapp
    depends_on:
      - postgres
      - redis

  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

Типові помилки

N+1 проблема

# Погано: N+1 запитів
users = User.query.all()              # 1 запит
for user in users:
    print(user.orders)                # N запитів (по одному на user)

# Добре: 1-2 запити
users = User.query.options(
    joinedload(User.orders)
).all()

Відсутність індексів

-- Повільно (Full Table Scan)
SELECT * FROM logs WHERE created_at > '2026-01-01';

-- Швидко (Index Scan)
CREATE INDEX idx_logs_created ON logs(created_at);
SELECT * FROM logs WHERE created_at > '2026-01-01';

SELECT *

-- Погано: тягнемо всі колонки
SELECT * FROM users;

-- Добре: тільки потрібні
SELECT id, name, email FROM users;

Див. також

Шлях: services/databases/intro.md

UMTC Wiki © 2026 | Ukrainian Military Tactical Communications