Базы данных SQL PostgreSQL
21 вопросов и ответов в разделе Базы данных SQL PostgreSQL.
Вопросы этого раздела
- Для чего нужны индексы?
- Как работает B-tree индекс?
- Что такое составной индекс?
- Когда стоит создавать индекс?
- Какие недостатки индексов?
- Что такое кардинальность индекса?
- Какие типы JOIN существуют?
- В чём разница между INNER JOIN и LEFT JOIN?
- Что лучше: JOIN или подзапрос?
- Что такое коррелированный подзапрос?
- В чём разница между WHERE и HAVING?
- Что делает GROUP BY?
- Когда использовать HAVING?
- Что такое оконные функции (Window Functions)?
- Что делает ROW_NUMBER()?
- Что делает RANK() и DENSE_RANK()?
- Как работает MVCC в PostgreSQL?
- Что такое VACUUM в PostgreSQL?
- Зачем нужен ANALYZE?
- Что такое explain plan?
- Как оптимизировать медленные запросы?
Навигатор по разделу
21 вопрос для подготовки к собеседованию на Middle Java Developer.
📋 Все вопросы
| # | Вопрос | Уровень сложности |
|---|---|---|
| 1 | Для чего нужны индексы | ⭐⭐ |
| 2 | Как работает B-tree индекс | ⭐⭐⭐ |
| 3 | Что такое составной индекс | ⭐⭐ |
| 4 | Когда стоит создавать индекс | ⭐⭐ |
| 5 | Какие недостатки индексов | ⭐⭐ |
| 6 | Что такое кардинальность индекса | ⭐⭐⭐ |
| 7 | Какие типы JOIN существуют | ⭐⭐⭐ |
| 8 | В чём разница между INNER JOIN и LEFT JOIN | ⭐⭐ |
| 9 | Что лучше JOIN или подзапрос | ⭐⭐⭐ |
| 10 | Что такое коррелированный подзапрос | ⭐⭐⭐ |
| 11 | В чём разница между WHERE и HAVING | ⭐ |
| 12 | Что делает GROUP BY | ⭐⭐ |
| 13 | Когда использовать HAVING | ⭐ |
| 14 | Что такое оконные функции | ⭐⭐⭐ |
| 15 | Что делает ROW_NUMBER() | ⭐⭐ |
| 16 | Что делает RANK() и DENSE_RANK() | ⭐⭐ |
| 17 | Как работает MVCC в PostgreSQL | ⭐⭐⭐ |
| 18 | Что такое VACUUM в PostgreSQL | ⭐⭐⭐ |
| 19 | Зачем нужен ANALYZE | ⭐⭐⭐ |
| 20 | Что такое explain plan | ⭐⭐ |
| 21 | Как оптимизировать медленные запросы | ⭐⭐⭐ |
🗺️ Карта зависимостей тем
┌─────────────────────────────────────────┐
│ 21. Оптимизация запросов (Центральная) │
│ pg_stat_statements → EXPLAIN → Fix │
└──────┬──────────┬──────────┬────────────┘
│ │ │
┌────────────┘ │ └────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ ИНДЕКСЫ (1-6) │ │ JOIN (7-10) │ │ ПЛАНИРОВЩИК │
│ 1. Зачем │ │ 7. Типы JOIN │ │ 19. ANALYZE │
│ 2. B-tree │ │ 8. INNER vs LEFT │ │ 20. EXPLAIN │
│ 3. Составной │ │ 9. JOIN vs подзапрос│ │ │
│ 4. Когда создать│ │ 10. Коррелированный │ └────────┬─────────┘
│ 5. Недостатки │ │ подзапрос │ │
│ 6. Кардинальность│ └─────────────────────┘ │
└────────┬────────┘ │
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────────┐
│ MVCC и ОБСЛУЖИВАНИЕ (17-18) │
│ 17. MVCC (xmin/xmax, HOT, Hint Bits, XID Wraparound) │
│ 18. VACUUM (dead tuples, Bloat, pg_repack, autovacuum) │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ ГРУППИРОВКА и ОКНА (11-16) │
│ 11. WHERE vs HAVING │
│ 12. GROUP BY (HashAggregate, GroupAggregate) │
│ 13. Когда HAVING │
│ 14. Оконные функции (ROWS, RANGE, FILTER) │
│ 15. ROW_NUMBER() │
│ 16. RANK() / DENSE_RANK() │
└──────────────────────────────────────────────────────────────────┘
🎯 Рекомендуемый порядок изучения
🟢 Уровень Junior (недели 1-2)
| Шаг | Тема | Файлы | Цель |
|---|---|---|---|
| 1 | Основы индексов | Q1, Q4, Q5 | Зачем нужны, когда создавать, недостатки |
| 2 | Основы JOIN | Q7, Q8 | Типы JOIN, INNER vs LEFT |
| 3 | WHERE / HAVING / GROUP BY | Q11, Q12, Q13 | Порядок выполнения, агрегация |
| 4 | MVCC базовый | Q17 (Junior) | Зачем MVCC, UPDATE = DELETE + INSERT |
| 5 | VACUUM базовый | Q18 (Junior) | Зачем VACUUM, обычный vs FULL |
| 6 | EXPLAIN базовый | Q20 (Junior) | Как читать план |
| 7 | ROW_NUMBER, RANK | Q15, Q16 (Junior) | Нумерация и ранжирование |
🟡 Уровень Middle (недели 3-4)
| Шаг | Тема | Файлы | Цель |
|---|---|---|---|
| 1 | B-tree внутренности | Q2, Q3, Q6 | Структура, составные, кардинальность |
| 2 | Физические JOIN | Q7 (Middle/Senior) | Nested Loop, Hash, Merge |
| 3 | Подзапросы | Q9, Q10 | Semi-Join, SubPlan, декорреляция |
| 4 | Оконные функции | Q14, Q15, Q16 | ROWS vs RANGE, FILTER, индексы |
| 5 | VACUUM детали | Q18 (Middle) | Autovacuum, Hot Standby, Cost-based |
| 6 | ANALYZE | Q19 | Статистика, MCV, correlation |
| 7 | Оптимизация | Q21 | Алгоритм, частые проблемы |
🔴 Уровень Senior (недели 5-6)
| Шаг | Тема | Файлы | Цель |
|---|---|---|---|
| 1 | B-tree internals | Q2 (Senior) | Lehman-Yao, High Key, дедупликация |
| 2 | JOIN оптимизация | Q7 (Senior) | GEQO, Join Reordering, Memoize |
| 3 | LATERAL + Memoize | Q9, Q10 (Senior) | PG 14+, Hits/Misses, CTE |
| 4 | MVCC глубина | Q17 (Senior) | Hint Bits, HOT, SSI, CLOG, Wraparound |
| 5 | VACUUM глубина | Q18 (Senior) | Visibility Map, Parallel, pg_repack |
| 6 | ANALYZE глубина | Q19 (Senior) | Extended Statistics, Reservoir Sampling |
| 7 | EXPLAIN глубина | Q20 (Senior) | Generic vs Custom, JIT, WAL |
| 8 | Системная оптимизация | Q21 (Senior) | Plan Cache, денормализация, pgBouncer |
🔗 Ключевые связи между темами
Тема: Индексы
Q1 (Зачем) → Q2 (B-tree) → Q3 (Составной) → Q4 (Когда) → Q5 (Недостатки) → Q6 (Кардинальность)
↓
Q21 (Оптимизация запросов)
Ключевые связи:
- Q1 ↔ Q17 (MVCC): HOT-обновления невозможны для индексированных колонок
- Q2 ↔ Q18 (VACUUM): Bloat → REINDEX
- Q3 ↔ Q6 (Кардинальность): порядок колонок по селективности
- Q4 ↔ Q19 (ANALYZE): статистика влияет на выбор индекса планировщиком
- Q5 ↔ Q21 (Оптимизация): Write Amplification, баланс индексов
Тема: JOIN и подзапросы
Q7 (Типы JOIN) → Q8 (INNER vs LEFT) → Q9 (JOIN vs подзапрос) → Q10 (Коррелированный)
↓
Q20 (EXPLAIN: ищите SubPlan)
Ключевые связи:
- Q7 ↔ Q20 (EXPLAIN): физические стратегии в плане (Nested Loop, Hash, Merge)
- Q8 ↔ Q11 (WHERE vs HAVING): фильтр на правой таблице → в ON, не в WHERE
- Q9 ↔ Q10: Semi-Join, декорреляция, SubPlan vs InitPlan
- Q10 ↔ Q14 (Оконные функции): оконные функции как альтернатива коррелированным подзапросам
Тема: GROUP BY и оконные функции
Q11 (WHERE vs HAVING) → Q12 (GROUP BY) → Q13 (Когда HAVING)
↓
Q14 (Оконные функции) → Q15 (ROW_NUMBER) → Q16 (RANK)
Ключевые связи:
- Q11 ↔ Q12: WHERE до GROUP BY, HAVING после
- Q12 ↔ Q14: оконные функции НЕ схлопывают строки (в отличие от GROUP BY)
- Q13 ↔ Q14: оконные функции считаются ПОСЛЕ HAVING → подзапрос
- Q14 ↔ Q15, Q16: ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK
Тема: MVCC и обслуживание
Q17 (MVCC) → Q18 (VACUUM) → Q19 (ANALYZE) → Q20 (EXPLAIN) → Q21 (Оптимизация)
Ключевые связи:
- Q17 ↔ Q18: MVCC создаёт dead tuples → VACUUM удаляет
- Q18 ↔ Q19: Autovacuum запускает ANALYZE
- Q19 ↔ Q20: Устаревшая статистика → wrong plan → ANALYZE
- Q20 ↔ Q21: EXPLAIN (ANALYZE, BUFFERS) — главный инструмент оптимизации
🎓 Шпаргалка: что знать для каждого уровня
🟢 Junior
- Что такое индекс и зачем нужен
- Типы JOIN (INNER, LEFT, RIGHT, FULL, CROSS)
- WHERE vs HAVING: когда что использовать
- GROUP BY + агрегатные функции (COUNT, SUM, AVG)
- MVCC: читатели не блокируют писателей
- VACUUM: зачем нужен, обычный vs FULL
🟡 Middle
- B-tree структура, составные индексы, правило левого префикса
- Физические стратегии JOIN (Nested Loop, Hash, Merge)
- EXISTS vs JOIN, SubPlan vs InitPlan
- Оконные функции: ROW_NUMBER, RANK, LAG/LEAD
- Autovacuum: threshold, scale_factor, настройка
- ANALYZE: статистика, n_distinct, MCV
- EXPLAIN (ANALYZE, BUFFERS): чтение плана
🔴 Senior
- Lehman-Yao, High Key, дедупликация (PG 13+), Skip Scan эмуляция
- GEQO, Join Reordering, Outer Join Removal, Memoize (PG 14+)
- MVCC: Hint Bits, HOT, SSI, CLOG, XID Wraparound
- VACUUM: Visibility Map, Parallel, pg_repack, Cost-based
- Extended Statistics, Reservoir Sampling
- Generic vs Custom Plans, plan_cache_mode, JIT, WAL
- Системная оптимизация: денормализация, pgBouncer, Partitioning
📝 Формат каждого файла
Каждый файл содержит:
- 🟢 Junior Level — базовое понимание, простые аналогии, примеры
- 🟡 Middle Level — внутренности, типичные ошибки, практические примеры
- 🔴 Senior Level — deep dive, edge cases, production experience, monitoring
- 🎯 Шпаргалка для интервью — ключевые тезисы, частые вопросы, красные флаги, связанные темы