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) выглядит так:
INSERT или использует команду COPY для быстрой загрузки данных в хранилище.Для подключения к базам данных используются драйверы, такие как psycopg2 (для PostgreSQL) или ORM (SQLAlchemy), но для высокой производительности инженеры предпочитают «сырые» SQL-запросы и пакетную вставку (batch insert).
Итоги
* Эффективность Python: Используйте множества (set) для быстрого поиска и генераторы (yield) для обработки больших файлов, чтобы экономить память.
* Читаемость SQL: Используйте CTE (WITH) вместо вложенных подзапросов для структурирования сложной логики.
* Аналитика в SQL: Оконные функции (OVER) позволяют проводить сложные вычисления (нарастающий итог, ранжирование) без группировки строк.
* Обработка NULL: Всегда учитывайте возможное наличие NULL значений и обрабатывайте их через COALESCE, чтобы не сломать вычисления.