Подготовка к собеседованию — Дата-инженер
Колода из 312+ карточек с вопросами для собеседования по направлению «Дата-инженер» — по темам и уровню сложности, с возвратом ровно перед тем, как вы забудете. Посмотрите несколько карточек ниже, затем выберите доступ, чтобы учить всё направление по расписанию в стиле Anki (SM-2).
7 дней бесплатно на месяц или год · все функции включены.
Что внутри
Все темы направления, сгруппированные так, как вы будете их учить.
Моделирование данных и хранилища
11 карточекETL/ELT и пайплайны
11 карточекSpark и распределённая обработка
10 карточекСтриминг и Kafka
10 карточекХранение и форматы файлов
9 карточекSQL и оптимизация запросов
10 карточекКачество данных и оркестрация
9 карточекАрхитектура данных и системный дизайн
8 карточекPython
122 карточкиБазы данных
42 карточкиDevOps и инфраструктура
35 карточекПоведенческое интервью
35 карточекПримеры вопросов
Несколько карточек из колоды — откройте ответ, затем выберите доступ, чтобы учить весь набор по расписанию.
Чем OLTP отличается от OLAP и почему аналитику не гоняют на боевой OLTP-базе?
Чем OLTP отличается от OLAP и почему аналитику не гоняют на боевой OLTP-базе?
Короткий ответ: OLTP обслуживает короткие транзакции — вставку и обновление отдельных строк с низкой задержкой, а OLAP отвечает на аналитические запросы, сканирующие миллионы строк. OLTP хранит данные построчно, OLAP — колоночно. Тяжёлую аналитику не гоняют на боевой OLTP-базе, потому что она конкурирует за ресурсы с транзакциями и роняет latency продакшена.
Подробно:
- Профиль нагрузки — OLTP: много мелких операций (
INSERT/UPDATEпо первичному ключу); OLAP: мало тяжёлых запросов сGROUP BYи агрегациями. - Модель хранения — построчное хранение читает всю строку целиком (удобно для транзакций), колоночное читает только нужные столбцы и лучше сжимается (удобно для аналитики).
- Нормализация — OLTP нормализован (3NF) ради целостности при записи, OLAP денормализован ради скорости чтения.
- Изоляция ресурсов — аналитический скан забивает буферный кэш и диск, из-за чего транзакции начинают ждать.
| Критерий | OLTP | OLAP |
|---|---|---|
| Задача | транзакции | аналитика |
| Операции | чтение/запись строк | агрегации по колонкам |
| Хранение | построчное | колоночное |
| Нормализация | 3NF | денормализация (звезда) |
| Метрика | latency, TPS | throughput скана |
⚠️ Частая ошибка: гонять отчётность прямо по продакшен-базе. Данные выгружают в отдельное хранилище (ETL/ELT), чтобы аналитика не мешала транзакциям.
В чём разница между ETL и ELT, почему ELT победил с приходом облачных хранилищ и когда ETL всё ещё оправдан?
В чём разница между ETL и ELT, почему ELT победил с приходом облачных хранилищ и когда ETL всё ещё оправдан?
Короткий ответ: ETL трансформирует данные до загрузки (на отдельном движке), ELT сначала грузит сырые данные в хранилище, а трансформации выполняет уже внутри него на SQL. ELT стал стандартом, потому что облачные MPP-хранилища (Snowflake, BigQuery, Redshift) дёшево масштабируют вычисления и разделяют storage/compute.
Подробно:
- ETL — трансформация на промежуточном движке (раньше — дорогие ETL-серверы). В хранилище попадают только готовые, «чистые» данные. Минус: логика заперта в инструменте, а сырьё теряется.
- ELT — грузим сырой слой как есть, трансформируем через dbt/SQL. Плюс: сырьё сохраняется, трансформации версионируются в Git, масштабирование берёт на себя хранилище.
- Почему ELT победил — разделение storage/compute сделало вычисления в хранилище дешёвыми и эластичными; аналитику стало удобнее держать в SQL.
| Критерий | ETL | ELT |
|---|---|---|
| Где трансформация | На отдельном движке | Внутри хранилища |
| Сырой слой | Обычно теряется | Сохраняется |
| Масштабирование | Ограничено движком | Эластичное (MPP) |
| Типичный стек | Informatica, SSIS | Fivetran + dbt + Snowflake |
Когда ETL всё ещё нужен: тяжёлые преобразования до попадания в хранилище, маскирование PII/комплаенс (нельзя грузить сырьё), или источник, который проще привести к схеме на лету.
⚠️ Частая ошибка: думать, что ELT — это «без трансформаций». Трансформации никуда не делись, они просто переехали в хранилище и выполняются после загрузки.
Опишите архитектуру Spark: драйвер, экзекьюторы, cluster manager. Как задание разбивается на jobs, stages и tasks?
Опишите архитектуру Spark: драйвер, экзекьюторы, cluster manager. Как задание разбивается на jobs, stages и tasks?
Короткий ответ: Драйвер строит план и координирует выполнение, cluster manager (YARN, Kubernetes, Standalone) выделяет ресурсы, а экзекьюторы на воркерах выполняют задачи и хранят данные в памяти. Каждый экшен запускает job, который планировщик режет на стадии по границам шафла, а стадию — на задачи по числу партиций.
Подробно:
- Драйвер — процесс с вашим кодом и
SparkSession. Строит логический и физический план, DAG стадий, планирует задачи и собирает результаты. Падение драйвера убивает всё приложение. - Cluster manager — договаривается о ресурсах: сколько экзекьюторов, сколько ядер и памяти на каждый. Сам вычислениями не занимается.
- Экзекьюторы — JVM-процессы на воркерах. Выполняют задачи, кэшируют партиции, отдают данные через shuffle. Живут всё время работы приложения.
- Иерархия работы —
Job(на каждый экшен) →Stage(границы по шафлу) →Task(одна задача на одну партицию, минимальная единица параллелизма).
┌──────────────┐
│ Драйвер │ план + DAG + планировщик
│ SparkSession │
└──────┬───────┘
│ запрос ресурсов
┌──────▼───────┐
│Cluster Manager│ YARN / K8s / Standalone
└──────┬───────┘
┌──────────┼──────────┐
┌────▼────┐ ┌───▼────┐ ┌───▼────┐
│Экзекьютор│ │Экзекьютор│ │Экзекьютор│ задачи + кэш
└─────────┘ └────────┘ └────────┘
⚠️ Частая ошибка: путать ядра экзекьютора с задачами — параллелизм ограничен число экзекьюторов × ядер, и если партиций меньше, чем слотов, часть ядер простаивает.
Как партиции и консьюмер-группы дают параллелизм, и как соотносятся число партиций и число консьюмеров?
Как партиции и консьюмер-группы дают параллелизм, и как соотносятся число партиций и число консьюмеров?
Короткий ответ: Партиция — единица параллелизма: внутри консьюмер-группы каждую партицию читает ровно один консьюмер. Поэтому эффективный параллелизм ограничен числом партиций — лишние консьюмеры сверх этого простаивают.
Подробно:
- Консьюмер-группа — набор консьюмеров с общим
group.id, между которыми партиции распределяются (rebalance). Каждая партиция закреплена за одним консьюмером группы. - Порядок гарантируется только внутри партиции. Больше партиций → больше параллелизма, но нет глобального порядка по топику.
- Соотношение: консьюмеров ≤ партиций для полной загрузки. Если консьюмеров больше — избыток простаивает без работы.
- Масштабирование: партиции задают потолок. Их число легко увеличить, но не уменьшить, и это меняет распределение ключей по партициям.
| Партиций | Консьюмеров | Итог |
|---|---|---|
| 4 | 2 | по 2 партиции на консьюмера |
| 4 | 4 | по 1 партиции — максимум параллелизма |
| 4 | 6 | 4 работают, 2 простаивают |
⚠️ Частая ошибка: добавлять консьюмеров ради ускорения, забыв, что потолок — число партиций. Сверх него консьюмеры сидят без назначенных партиций.
Чем колоночное хранение отличается от строкового и почему для аналитики быстрее и дешевле именно колоночный формат?
Чем колоночное хранение отличается от строкового и почему для аналитики быстрее и дешевле именно колоночный формат?
Короткий ответ: В строковом формате значения одной записи лежат рядом, в колоночном — рядом лежат все значения одной колонки. Для аналитических запросов (агрегаты по нескольким колонкам из десятков) колоночный формат читает только нужные колонки, лучше сжимается и поддерживает предикатный пушдаун — отсюда меньше I/O и ниже стоимость.
Подробно:
- Проекция колонок (projection pushdown) — запросу нужны 3 колонки из 50, и колоночный движок читает с диска только эти три. Строковый формат вынужден прочитать строку целиком.
- Сжатие — в колонке лежат однотипные значения (один тип, похожие данные), поэтому dictionary-, run-length- и delta-кодирование дают степень сжатия в разы выше, чем на разнородной строке.
- Предикатный пушдаун (predicate pushdown) — по хранимым min/max статистикам блока фильтр
WHERE date = ...пропускает целые блоки, не читая их. - Строковый формат выигрывает при точечных операциях: прочитать/записать запись целиком (OLTP, стриминг по одной записи).
Строковый (row): [id=1,name=A,ts=..][id=2,name=B,ts=..][id=3,...]
└── запись 1 ──┘└── запись 2 ──┘
Колоночный (columnar):
id: [1, 2, 3, ...] ← читаем только нужные
name: [A, B, C, ...] колонки, каждая
ts: [.., .., .., ...] сжата отдельно
⚠️ Частая ошибка: считать колоночный формат universally лучшим. Для построчной записи и чтения записи целиком (стриминг, транзакционные апдейты) строковый формат (Avro) эффективнее.
Как читать план выполнения запроса (EXPLAIN) и на что смотреть в первую очередь?
Как читать план выполнения запроса (EXPLAIN) и на что смотреть в первую очередь?
Короткий ответ: План читают снизу вверх и изнутри наружу: листья — это доступ к таблицам (Seq Scan / Index Scan), выше идут джойны и агрегации. Ищут самый дорогой узел, полные сканы больших таблиц под фильтром и выбранный метод джойна.
Подробно:
- Направление чтения — от самых вложенных узлов (чтение данных) к корню (итоговый результат). В
EXPLAIN ANALYZEсравнивают оценку (rows=) с фактом (actual rows): расхождение в разы выдаёт кривую статистику оптимизатора. - Способ доступа — Seq Scan (полный скан) против Index / Index Only Scan. Полный скан большой таблицы под селективным фильтром — первый кандидат на оптимизацию.
- Метод джойна — Nested Loop, Hash Join, Merge Join (см. таблицу).
- Дорогой узел — с наибольшим
cost/временем; на нём и концентрируют усилия.
| Метод | Когда выбирается | Цена |
|---|---|---|
| Nested Loop | малый внешний вход + индекс на внутреннем | дёшев на малых объёмах, иначе O(N·M) |
| Hash Join | большие несортированные наборы, эквиджойн | строит хеш-таблицу в памяти |
| Merge Join | оба входа отсортированы по ключу | выгоден при уже готовой сортировке |
EXPLAIN ANALYZE
SELECT o.id, c.name
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.created_at >= DATE '2026-01-01';
-- Hash Join (cost=... rows=...) <- метод джойна
-- -> Seq Scan on orders o <- полный скан: фильтр не по индексу
-- Filter: (created_at >= ...)
-- -> Hash
-- -> Seq Scan on customers c
⚠️ Частая ошибка: смотреть только на итоговый cost и игнорировать расхождение rows vs actual rows — именно оно выдаёт устаревшую статистику и выбор плохого плана.
Готовы закрепить навсегда?
Первая сессия — меньше минуты. Ваше будущее «я» на собеседовании скажет спасибо.
Вопросы об этом направлении
Как готовиться к собеседованию на «Дата-инженер»?
Учите концепции, которые придётся объяснять, а не только те, что умеете кодить. Направление «Дата-инженер» в RecallDeck даёт 312+ отобранных вопросов и возвращает каждый по расписанию в стиле Anki (SM-2) ровно перед тем, как вы забудете — чтобы на собеседовании ответы были под рукой.
Какие темы охватывает направление «Дата-инженер»?
Направление «Дата-инженер» разбито на ключевые области, которые реально проверяют на таких собеседованиях, — по темам и уровню сложности (Concept, Junior, Middle, Senior). Полный план и примеры вопросов можно посмотреть выше до входа.
Помогает ли интервальное повторение в подготовке к «Дата-инженер»?
Да. Активно вспоминать ответ и честно себя оценивать — куда прочнее для памяти, чем перечитывать заметки. RecallDeck планирует каждую карту «Дата-инженер» так, чтобы она вернулась перед моментом забывания: ежедневных повторений становится меньше, а знания держатся.
Можно попробовать направление «Дата-инженер» до оплаты?
Да. Месячный и годовой варианты включают семь пробных дней со всем направлением «Дата-инженер», полным планировщиком SM-2, статистикой, гибким темпом и блиц-режимом. Отменить можно онлайн до первого списания.