Путь к профессии Junior Data Engineer

Этот курс поможет освоить ключевые навыки инженера данных с нуля до уровня Junior. Вы изучите необходимый стек технологий, от баз данных до Big Data, и узнаете, как успешно пройти собеседование.

1. Основы программирования: Python и продвинутый SQL для работы с данными

Основы программирования: Python и продвинутый SQL для работы с данными

Профессия Data Engineer строится на двух фундаментальных навыках: умении писать код для автоматизации процессов (Python) и умении эффективно извлекать и преобразовывать данные (SQL). В отличие от аналитиков, инженеру данных недостаточно просто написать запрос, который «работает». Код должен быть оптимизированным, читаемым и устойчивым к ошибкам.

Python для инженера данных: за пределами скриптов

Python стал стандартом в инженерии данных благодаря богатой экосистеме библиотек (Pandas, PySpark, Airflow). Однако, прежде чем изучать фреймворки, необходимо глубоко понимать базовые структуры данных и механизмы языка. Неэффективное использование памяти может «уронить» пайплайн при обработке больших объемов данных.

Структуры данных и их производительность

Выбор правильной структуры данных определяет скорость работы алгоритма. Рассмотрим разницу между списком (list) и множеством (set) при поиске элементов.

Предположим, нам нужно проверить наличие ID пользователя в базе из 1 миллиона записей. В списке Python вынужден перебирать элементы по одному, пока не найдет нужный. В множестве поиск происходит мгновенно благодаря хешированию.

Математически это описывается через временную сложность («O-нотация»):

где — время поиска в списке, — количество элементов, — линейная зависимость (чем больше элементов, тем дольше поиск).

где — время поиска в множестве, — константное время (время поиска не зависит от количества элементов).

!Графическое сравнение производительности поиска в множестве и списке

Генераторы и итераторы

Одна из частых ошибок новичков — попытка загрузить весь файл в оперативную память. Если файл весит 10 ГБ, а оперативной памяти всего 8 ГБ, программа завершится с ошибкой MemoryError.

Для обработки больших потоков данных используются генераторы. Они возвращают элементы по одному, не загружая весь массив в память. В Python для этого используется ключевое слово yield.

Пример чтения огромного лог-файла:

Использование генераторов позволяет обрабатывать файлы любого размера, ограничиваясь потреблением памяти, необходимым для хранения только одной строки.

Продвинутый SQL: от выборки к аналитике

SQL для инженера данных — это не просто SELECT * FROM table. Это инструмент для сложной трансформации данных на стороне базы данных, что часто быстрее, чем выгрузка данных в Python.

CTE (Common Table Expressions)

Вложенные подзапросы делают код нечитаемым. CTE (обобщенные табличные выражения) позволяют создавать именованные временные наборы данных, существующие только в рамках одного запроса. Это делает логику линейной и понятной.

Синтаксис использует конструкцию WITH:

Такой подход упрощает отладку: вы можете проверить каждый блок WITH отдельно.

Оконные функции (Window Functions)

Это самый мощный инструмент для аналитики внутри SQL. В отличие от GROUP BY, который схлопывает строки, оконные функции сохраняют исходное количество строк, но добавляют к ним агрегированные данные (например, сумму, среднее или ранг) в контексте определенной группы.

Ключевая конструкция: OVER (PARTITION BY ... ORDER BY ...).

!Принцип работы PARTITION BY и ORDER BY в оконных функциях

#### Пример: Нарастающий итог

Допустим, нам нужно посчитать, как росла выручка день за днем для каждого магазина.

Разберем элементы: * PARTITION BY store_id: вычисления идут независимо для каждого магазина. * ORDER BY sale_date: данные суммируются в хронологическом порядке. * SUM(amount): функция, которая применяется к окну.

Если у магазина были продажи 100, 200 и 50, результат running_total будет: 100, 300 (100+200), 350 (100+200+50).

#### Ранжирование: ROW_NUMBER, RANK, DENSE_RANK

Частая задача — найти «топ-3» записи в каждой категории. Для этого используются функции ранжирования. Важно понимать разницу между ними при наличии одинаковых значений:

| Значение | ROW_NUMBER() | RANK() | DENSE_RANK() | | :--- | :--- | :--- | :--- | | 100 | 1 | 1 | 1 | | 90 | 2 | 2 | 2 | | 90 | 3 | 2 | 2 | | 80 | 4 | 4 | 3 |

* ROW_NUMBER(): Всегда уникальный номер, даже при совпадении значений. * RANK(): При совпадении дает одинаковый ранг, но пропускает следующие номера (после двух 2-х мест идет 4-е). * DENSE_RANK(): При совпадении дает одинаковый ранг и НЕ пропускает номера (после двух 2-х мест идет 3-е).

Работа с NULL

В SQL NULL — это не ноль и не пустая строка, это отсутствие значения. Любая арифметическая операция с NULL дает NULL.

Пример ошибки:

Чтобы избежать потери данных при агрегации, используйте функцию COALESCE, которая возвращает первый аргумент, не являющийся NULL.

Если tax равен NULL, он будет заменен на 0, и сумма посчитается корректно.

Взаимодействие Python и SQL

В работе Data Engineer эти инструменты редко используются изолированно. Типичный паттерн ETL-процесса (Extract, Transform, Load) выглядит так:

  • Extract: Python подключается к источнику (API, файл) и забирает данные.
  • Transform: Python очищает данные (удаляет дубликаты, форматирует даты).
  • Load: Python формирует SQL-запрос INSERT или использует команду COPY для быстрой загрузки данных в хранилище.
  • Для подключения к базам данных используются драйверы, такие как psycopg2 (для PostgreSQL) или ORM (SQLAlchemy), но для высокой производительности инженеры предпочитают «сырые» SQL-запросы и пакетную вставку (batch insert).

    Итоги

    * Эффективность Python: Используйте множества (set) для быстрого поиска и генераторы (yield) для обработки больших файлов, чтобы экономить память. * Читаемость SQL: Используйте CTE (WITH) вместо вложенных подзапросов для структурирования сложной логики. * Аналитика в SQL: Оконные функции (OVER) позволяют проводить сложные вычисления (нарастающий итог, ранжирование) без группировки строк. * Обработка NULL: Всегда учитывайте возможное наличие NULL значений и обрабатывайте их через COALESCE, чтобы не сломать вычисления.

    2. Хранение данных: Проектирование реляционных баз, NoSQL и архитектура DWH

    Хранение данных: Проектирование реляционных баз, NoSQL и архитектура DWH

    Инженер данных не просто пишет код, он строит системы, которые должны надежно хранить терабайты информации и отдавать их аналитикам за секунды. Выбор правильного хранилища и способа организации данных (моделирования) — это критический навык. Если вы попытаетесь построить аналитический отчет на базе данных, спроектированной для обработки транзакций, вы «положите» продакшн. Если же вы будете хранить финансовые транзакции в базе, не гарантирующей целостность, компания потеряет деньги.

    Реляционные базы данных (RDBMS) и OLTP

    Реляционные базы данных (PostgreSQL, MySQL) — это стандарт для операционных систем. Они хранят данные в таблицах, связанных между собой ключами. Их главная задача — быстрая обработка транзакций (OLTP — Online Transaction Processing): создание заказа, регистрация пользователя, списание средств.

    Фундамент RDBMS — это ACID. Это набор требований, гарантирующий сохранность данных:

  • Atomicity (Атомарность): Транзакция выполняется целиком или не выполняется вовсе. Нельзя списать деньги, но не начислить товар.
  • Consistency (Согласованность): Данные всегда соответствуют правилам (ограничениям, типам данных).
  • Isolation (Изолированность): Параллельные транзакции не мешают друг другу.
  • Durability (Долговечность): Если система сказала «ОК», данные сохранены на диске, даже если сервер выключат через миллисекунду.
  • Нормализация: борьба с дубликатами

    При проектировании OLTP-систем используется нормализация — процесс разделения данных на таблицы для устранения избыточности.

    Представьте таблицу заказов, где в каждой строке записан адрес клиента. Если клиент переедет, нам придется обновлять тысячи строк. В нормализованной базе адрес хранится в таблице users один раз, а в таблице orders есть только ссылка user_id.

    Это экономит место и упрощает обновление, но замедляет чтение, так как требует операций JOIN.

    NoSQL: Когда реляционной модели недостаточно

    С ростом объемов данных (Big Data) и требований к скорости разработки, классические RDBMS стали узким местом. Появились NoSQL решения, которые жертвуют некоторыми гарантиями ACID ради масштабируемости и гибкости.

    CAP-теорема

    Это фундаментальный закон распределенных систем. Он гласит, что распределенная база данных может обеспечить только два из трех свойств одновременно:

    !Визуализация CAP-теоремы и классификация баз данных

  • Consistency (Согласованность): Все узлы кластера видят одни и те же данные в любой момент времени.
  • Availability (Доступность): Каждый запрос получает ответ (успех или ошибка), даже если часть узлов упала.
  • Partition Tolerance (Устойчивость к разделению): Система продолжает работать, даже если связь между узлами потеряна.
  • В реальности сеть может отказать в любой момент, поэтому Partition Tolerance (P) обязателен для распределенных систем. Инженеру приходится выбирать между CP (данные точные, но база может «прилечь») и AP (база всегда отвечает, но данные могут быть устаревшими на пару секунд).

    Типы NoSQL баз

    * Key-Value (Redis): Простейшая структура «ключ-значение». Идеально для кеширования и сессий. Работает в памяти, невероятно быстро. * Document (MongoDB): Хранит данные в JSON-подобных документах. Схема гибкая: у одного пользователя может быть поле «телефон», у другого — нет. * Column-family (Cassandra): Данные хранятся по колонкам, а не по строкам. Обеспечивает колоссальную скорость записи.

    Архитектура DWH (Data Warehouse)

    Для аналитики OLTP-базы не подходят. Сложные аналитические запросы (OLAP — Online Analytical Processing) блокируют таблицы и мешают работе пользователей. Поэтому данные выгружают в специальное хранилище — DWH.

    Схема «Звезда» (Star Schema)

    Это стандарт де-факто для проектирования витрин данных в DWH. Данные делятся на два типа таблиц:

  • Таблицы фактов (Fact Tables): Содержат события (покупки, клики, просмотры). Они длинные (миллиарды строк), но узкие. Содержат ключи и метрики (числа).
  • Таблицы измерений (Dimension Tables): Содержат описания (кто купил, где, когда). Они короткие, но широкие.
  • !Схема Звезда: Таблица фактов в центре и измерения вокруг

    Пример запроса в такой схеме: «Покажи сумму продаж (из Фактов) по городам (из Измерения Магазинов)».

    Колоночное хранение (Columnar Storage)

    Аналитические базы данных (ClickHouse, Vertica, BigQuery) физически хранят данные иначе, чем PostgreSQL.

    В классической (строковой) базе данные лежат на диске строка за строкой: [ID=1, Name=Ivan, City=Moscow], [ID=2, Name=Maria, City=Omsk]

    Чтобы посчитать количество пользователей из Москвы, базе нужно прочитать с диска всю строку, включая ненужное имя.

    В колоночной базе данные лежат по колонкам: [ID: 1, 2], [Name: Ivan, Maria], [City: Moscow, Omsk]

    Запрос читает только колонку City. Это ускоряет аналитику в десятки и сотни раз.

    !Разница в чтении данных между строковыми и колоночными базами

    Оценка объема данных

    Инженер данных должен уметь оценивать необходимый объем хранилища. Для таблицы фактов размер можно грубо оценить по формуле:

    где — общий размер таблицы, — количество строк (событий), — количество колонок, — размер -й колонки в байтах.

    Например, если у нас 1 миллиард строк (), и каждая строка занимает 50 байт (4 ключа по 8 байт + 2 метрики по 8 байт + дата 2 байта), то:

    В колоночных базах благодаря сжатию одинаковых значений этот объем может уменьшиться в 10 раз, до 5 ГБ.

    Data Lake и современные тренды

    Хранить все в DWH дорого и сложно (нужна схема). Поэтому появился подход Data Lake (Озеро данных) — свалка «сырых» данных (файлы, логи, картинки) в дешевом хранилище (S3, HDFS).

    Современный тренд — Lakehouse, попытка объединить управление и ACID-транзакции из DWH с дешевизной и гибкостью Data Lake (примеры: Delta Lake, Apache Iceberg).

    Итоги

  • OLTP vs OLAP: Используйте PostgreSQL для транзакций (магазин работает) и ClickHouse/BigQuery для аналитики (директор смотрит отчет). Не смешивайте эти нагрузки.
  • CAP-теорема: В распределенных системах всегда приходится чем-то жертвовать. Для важных данных выбирайте согласованность (CP), для высокой нагрузки — доступность (AP).
  • Моделирование: В DWH используйте схему «Звезда». Разделяйте факты (что произошло) и измерения (контекст события).
  • Колоночное хранение: Для аналитики больших данных колоночные базы эффективнее строковых, так как читают с диска только нужные поля и отлично сжимают данные.