TGViewer
Channel Public Channel
Дмитрий Кузьмин | Инженерия данных

Дмитрий Кузьмин | Инженерия данных

@kuzmin_dmitry91

Путь Data engineer от Junior до Lead.

Делюсь мыслями, рабочими кейсами, обучением. Блог для junior - middle DE.

Мой профиль: @dim4eg91
Сайт: https://kuzmin-dmitry.ru
Практикум Data engineer: https://kuzmin-dmitry.ru/de_practicum
Subscribers
1.75K
Photos
110
Videos
6
Links
88
Recent Posts 15 shown
Post #263 259
Можно отдельно изучить SQL, Spark и Airflow, а потом всё равно не понимать, как связать их в один работающий пайплайн 🥵

Вчера получил отзыв от участника четвёртого потока. Меня особенно зацепило, что он отметил не отдельные технологии, а весь путь от SQL и Spark до Airflow и Metabase, а также большое количество проверок, которые заставляют глубже разбираться в решении.

Для меня это прям супер точное попадание в идею практикума.

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

После этого я лично проверяю схемы, скрипты и данные. На каждое домашнее задание пишу рецензию: показываю, где результат может быть неверным, что стоит дополнительно проверить и как исправить решение. Обычно отвечаю в течение суток, хотя при высокой загрузке иногда требуется больше времени.

🛡 Такой формат требует времени. В среднем проект занимает 6–8 недель, а самые быстрые участники собирали полный контур примерно за месяц. Для старта достаточно среднего SQL, базового Python и готовности работать в терминале. Spark и Airflow заранее знать не нужно: они появляются по ходу проекта вместе с конкретной задачей.

В конце остаётся связный репозиторий, где данные проходят путь от исходных файлов до витрин: PostgreSQL и MinIO используются для хранения, Spark для обработки, Airflow для оркестрации, а проверки качества помогают контролировать результат перед загрузкой в BI.

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

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

🤔 Если ты уже пишешь SQL, но пока не собирал весь путь данных от исходного файла до BI, на странице можно посмотреть программу, примеры сдач и проверить свою входную точку.

Шестой поток стартует 12 октября.
Подробнее - https://kuzmin-dmitry.ru/de_practicum
Stepik - https://stepik.org/a/297679

#DEпрактикум
  • ❤ 6
  • 👍 3
  • 🔥 2
Post #262 484
Почему RAG-бот иногда отвечает «не знаю»

✍️ В августе я только начинал погружаться в RAG и собирал первую версию информационного бота для DE-практикума. Тогда задача выглядела довольно коротко: загрузить материалы курса, подключить LLM и научить её отвечать на вопросы.

Сейчас бот уже работает в бета-режиме, а схема внутри выросла в нормальный пайплайн. Хочу показать, что происходит между сообщением в Telegram и готовым ответом, и почему иногда правильный результат этого пайплайна звучит как «я не знаю».

📣 RAG расшифровывается как Retrieval-Augmented Generation, или генерация с дополненным контекстом. Перед ответом модель получает несколько фрагментов, которые система нашла специально под вопрос пользователя. В этих фрагментах и нужно искать основание для ответа.

Например, человек спрашивает:
Я аналитик, уверенно пишу JOIN и оконные функции, Python использую для небольших скриптов. Достаточно ли такой базы для входа и когда стартует следующий поток?


Теперь подробнее, что происходит:

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

Сначала бот определяет тему вопроса. Затем поиск находит в базе знаний фрагменты, близкие по смыслу. Каждый найденный фрагмент получает оценку близости: чем она выше, тем лучше текст соответствует вопросу. Актуальные условия бот получает отдельно и только после этого собирает общий контекст для модели.

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

Порог я проверяю на контрольных вопросах: смотрю, какие фрагменты нашлись, с какими оценками и хватает ли их для ответа. Отдельно прогоняю смешанные формулировки и вопросы, ответа на которые в базе нет.

До генерации слабые фрагменты отсекаются по порогу. Затем система проверяет, покрывает ли оставшийся контекст сам вопрос. Если человек спросил и про требования, и про дату старта, ответа только на первую часть недостаточно.

После генерации валидатор проверяет, подтверждаются ли основные утверждения контекстом и закрыты ли все части вопроса. Если нет, бот задаёт уточнение, отвечает только на подтверждённую часть или сообщает, что данных недостаточно.

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

Здесь ответ «я не знаю» становится полезной функцией. Неверная цена, дата старта или требование к участнику могут привести человека к неправильному решению. Поэтому я скорее приму меньше ответов, но с понятным основанием. Генерировать мусор ради высокой доли ответов здесь нет смысла.

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

⌨️ Вот, поэтому сейчас боту можно написать о своём опыте и спросить, подходит ли текущая база для практикума, что будет в модулях по Spark и Airflow или как устроена проверка работ: @de_practicum_info_bot

Шестой поток DE-практикума стартует 12 октября. Если бот ответит странно или пропустит часть вопроса, перешлите мне диалог. Такие примеры помогают точнее настроить поиск и пороги.

#материалы
#курсы
  • 👍 4
  • 🔥 3
  • ❤ 2
  • 🤔 1
Post #261 684
У блога появился свой герой 🐻

В последнее время здесь много пайплайнов, проверок качества, Spark и Airflow, поэтому я решил немного разбавить серьёзные разборы и собрал стикерпак с DE-медведем.

Внутри есть OOM, упавшие джобы, data skew, dependency hell, успешный backfill и тот самый момент, когда после обычного JOIN в таблице внезапно оказывается миллиард строк. В общем, почти стандартная рабочая неделя Data Engineer, только в виде медведя с ноутбуком.

Стикеры бесплатные, можно забирать и отправлять коллегам:

Забрать DE-медведя

У меня пока фаворит медведь после OOM, хотя again? тоже довольно жизненный 😅 Если будете использовать, напишите потом, какой стикер прижился больше всего и кадайте в комменты самый прикольный!
  • 🔥 11
  • ❤ 4
  • 🤩 3
  • 👍 1
Post #260 744
💬 Какой результат SQL отправить бизнесу?

Ребят, одна из частых ошибок в SQL-задачах состоит в том, что мы сразу открываем редактор, механически считаем показатель и отправляем заказчику готовую цифру. Я сам не раз на этом обжигался: запрос написан правильно, результат выглядит убедительно, а потом выясняется, что под одной и той же формулировкой мы понимали разные вещи.

Покажу на небольшом примере.

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

order_id | customer_id | order_date
---------+-------------+-----------
1001 | 1 | 2026-09-02
1002 | 1 | 2026-09-11
1003 | 2 | 2026-09-04
1004 | 3 | 2026-09-06
1005 | 3 | 2026-09-18
1006 | 4 | 2026-09-22


На первый взгляд задача простая, но по этим данным можно вернуть как минимум три правдоподобных ответа: 6, 4 или 2. Какой из них вы бы отправили менеджеру?

Попробуйте сначала выбрать свой вариант, а затем посмотреть разбор ниже.

Теперь разбираемся

Если выполнить COUNT(*), получится 6, но это количество заказов, поскольку одна строка в таблице соответствует одному заказу. Запрос выполнился правильно, только на вопрос о клиентах он не ответил.

COUNT(DISTINCT customer_id) вернёт 4. Это количество уникальных клиентов, которые сделали хотя бы один заказ в сентябре, и именно такой смысл чаще всего подразумевают под числом покупателей за период.

Если сгруппировать данные по customer_id и оставить клиентов с двумя и более заказами, получится 2. Но называть их повторными клиентами пока рано: мы видим только сентябрь и не знаем, покупали ли клиенты 2 и 4 раньше. Для одного бизнеса повторная покупка означает второй заказ внутри месяца, а для другого любой заказ после первой покупки за всё время.

Все три числа можно получить корректным SQL-запросом:

with customer_orders as (
select
customer_id,
count(*) as orders_cnt
from orders
where order_date >= '2026-09-01'
and order_date < '2026-10-01'
group by customer_id
)
select
sum(orders_cnt) as orders_cnt,
count(*) as buyers_cnt,
sum(
case
when orders_cnt >= 2 then 1
else 0
end
) as clients_with_2plus_orders
from customer_orders;


Обратите внимание на границу периода: условие order_date < '2026-10-01' безопаснее, чем попытка перечислить все возможные значения последнего дня сентября, особенно если в поле хранится не только дата, но и время.

Результат будет таким:

orders_cnt | buyers_cnt | clients_with_2plus_orders
-----------+------------+--------------------------
6 | 4 | 2


При этом правильного ответа на фразу «сколько клиентов было за месяц» всё ещё нет, пока мы не договорились о смысле метрики. Вместо того чтобы угадывать, я бы вернулся к менеджеру с конкретным вопросом:

Уточню смысл: считаем всех уникальных покупателей с заказом в сентябре, клиентов с двумя и более заказами внутри месяца или тех, кто в сентябре вернулся после своей первой покупки за всю историю?


В работе к этому добавятся статусы заказов, возвраты, границы периода и часовой пояс. Самая опасная ошибка здесь появляется ещё до написания SQL, когда расплывчатую формулировку превращают в точную цифру, а потом эта цифра попадает в отчёт и начинает выглядеть как факт.

Поэтому я бы не отправлял ни 6, ни 4, ни 2, пока не зафиксирован смысл метрики. Хороший запрос начинается с ответа на два вопроса: что означает одна строка исходных данных и какой бизнес-смысл должна иметь итоговая цифра.

❔ Если хотите проверить, где у вас заканчивается уверенный SQL, на сайте есть страница с небольшой диагностикой.

#материалы
kuzmin-dmitry.ru Практические курсы SQL для работы и собеседований Курсы SQL с практическими задачами: от SELECT, JOIN и GROUP BY до CTE, оконных функций и собеседований уровня Middle. Выберите подходящий маршрут.
  • 🔥 10
  • 👍 8
  • ❤ 1
Post #259 829
Когда пайплайн упал в пятницу в 18:30, но дежуришь не ты.

С пятницей! Пусть выходные пройдут отлично! 🥳
  • 😁 18
  • ❤ 9
  • 🔥 3
  • 💯 1
Post #258 859
Сначала выучу весь DE-стек

У меня переход в Data Engineering тормозился примерно на этой мысли.
Сначала нужно разобраться с Docker. Потом с Airflow. Ещё Spark, Kafka, облака, форматы хранения… Список рос, а момент «теперь можно собрать первый проект» всё откладывался.

У такой подготовки нет финиша. Всегда найдётся ещё один инструмент, который вроде бы надо изучить заранее.

Сейчас перед первым учебным проектом я бы проверял базу по трём вещам:

🟣 SQL. Могу написать запрос, соединить таблицы, посчитать агрегаты и объяснить, почему после JOIN строк стало больше.
🟡 Python. Могу прочитать файл, обработать данные и разобраться в чужом несложном коде.
🔘 Docker. Могу запустить контейнеры, проверить их состояние и посмотреть логи, если что-то сломалось.

Оконные функции стоит подтягивать по ходу работы с SQL. Слои хранилища, оркестрацию и Spark тоже проще осваивать, когда понятно, какую задачу ты ими решаешь.

Но как понять, хватает ли именно твоей базы?

Этот вопрос мне задают и про DE-практикум. Чтобы с ним было проще разобраться, я собрал информационного бота.

Недавно показывал, как изучаю LLM и n8n. Бот стал одним из результатов: я собрал материалы о практикуме, добавил контекст по программе, формату и входным требованиям, проверил ответы. Теперь можно попробовать альфа-версию.

Боту можно написать о своём опыте или сразу спросить то, что важно перед участием. Например:

Работаю аналитиком 1,5 года, знаю SQL на уровне оконок и питон использую для формирования отчетов (автоматический скрипт), умею читать функции. Этого достаточно для входа? И когда старт потока?

Что изучается в spark и airflow? Насколько детально и глубоко?

Как устроена поддержка и проверки домашек? Есть ли дедлайны?


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

✅ de_practicum_info_bot

В следующих постах покажу, как он устроен: как обрабатывает вопрос, откуда берёт информацию и что пришлось доработать, чтобы ответы стали полезными 😅
Telegram Дмитрий Кузьмин | Инженерия данных
  • 🔥 9
  • 👍 4
  • ❤ 2
Post #257 1.06K
Наконец-то нормальное объяснение JOIN 😆

С пятницей!
  • 😁 31
  • ❤ 5
  • 🔥 2
  • 👏 2
Post #255 952
112 650 строк загрузились. Этого достаточно? 😧

В одной из сдач по DE-практикуму в итоговой таблице получилось 112 650 строк. На первый взгляд всё нормально: загрузка прошла, таблица заполнилась, можно идти дальше и собирать витрину.

Но сначала нужно понять, что означает одна строка в этой таблице. В нашем случае это одна позиция заказа, а её уникальность определяется парой order_id и order_item_id.

Допустим, при сборке факта к позиции заказа присоединились две версии одного клиента. Запрос выполнится без ошибки, таблица заполнится, но строк станет больше, а выручка в отчёте окажется завышенной. Скорее всего, проблему заметят уже в BI, где искать её будет гораздо сложнее.

➡️ Поэтому отдельно проверяем, нет ли в факте повторяющихся позиций:

select
order_id,
order_item_id,
count(*) as row_count
from core.fct_order_items
group by
order_id,
order_item_id
having count(*) > 1;


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

↘️ На втором скрине эти проверки уже собраны в pipeline_smoke_check в Airflow. Количество дублей, пустых ключей и конфликтующих версий равно нулю, а размер текущей загрузки составляет те самые 112 650 строк.

Теперь эти проверки не нужно каждый раз повторять руками. При следующем запуске пайплайн выполнит их сам и сохранит результат для конкретной загрузки.

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


👍 Можно начинать с двух простых вопросов: что означает одна строка в таблице фактов и какие поля делают её уникальной? Если на них есть внятный ответ, дальше уже понятно, какие проверки нужно встроить в пайплайн.

#кейсы
  • 🔥 7
  • 👍 4
  • ❤ 3
Post #254 846
📢 6 вредных привычек для потери времени в Data Engineering

Собрал несколько плохих привычек, которые когда-то были у меня самого. Некоторые стоили пары часов, некоторые целого вечера, а одна чуть не снесла всё Docker-окружение.

1️⃣ Делать красиво раньше, чем правильно

Раньше я мог добавить ещё один CTE, переименовать все поля и начать оптимизацию до того, как проверил сам расчёт.

Проблема в том, что красивый запрос тоже может считать ерунду. Только место ошибки в нём искать сложнее.

Сейчас сначала собираю простой рабочий вариант, запускаю на небольшом сэмпле, проверяю количество строк, уровень данных и контрольные суммы, а потом уже можно рефакторить и оптимизировать.

2️⃣ Менять во время отладки сразу всё

Однажды я одновременно правил docker-compose, переносил WSL, чистил диск и переустанавливал окружение. В итоге потерял контейнеры, образы и случайно снёс Java runtime.

Когда меняешь пять вещей сразу, невозможно понять, какая из них помогла, а какая всё окончательно сломала.

Лучше поменять что-то одно, одну переменную, снять метрики, потом заново. И это правда работает, потому что получаешь одно изменение и можешь его объяснить.

3️⃣ Оставлять полезный код в tmp и ноутбуках

Кажется, что скрипт временный и больше не пригодится. Потом сессия падает, каталог очищается, а через месяц, как всегда это бывает, нужен именно этот код.

Теперь даже черновые скрипты стараюсь отправлять в Git. Пусть файл пока некрасивый, зато он не исчезнет вместе с окружением.

4️⃣ Доверять автоматически определённым типам

У меня разваливалась вставка из-за того, что один из выходных типов не совпал со схемой целевой таблицы. Логов было мало, поэтому до причины я дошёл далеко не сразу.

С тех пор в важных местах явно задаю схему, использую CAST и даже для пустых колонок фиксирую ожидаемый тип. Особенно при чтении CSV, перед INSERT и UNION.

5️⃣ Проверять всё руками и не оставлять след

Раньше я мог скопировать несколько запросов, руками заменить таблицы и даты, посмотреть результат и закрыть вкладку. Через неделю приходилось вспоминать, что именно я сверял.

Повторяющиеся проверки теперь стараюсь параметризовать, а важные результаты записывать в DQ-журнал: дата, таблица, название проверки, статус и значение.

6️⃣ Лечить медленный Spark добавлением ресурсов

Первая реакция на медленную или падающую Spark job понятная: дать больше памяти и ядер. Иногда это помогает. Иногда job просто дольше ждёт ресурсы, которых в очереди нет, а настоящая проблема остаётся в shuffle, перекосе данных или неудачном числе партиций.

Поэтому сначала смотрю план выполнения, Spark UI и ограничения кластера. И только потом добавляю ресурсы.

Все эти привычки поначалу выглядят как экономия времени.

⬇️ Делитесь своими плохими привычками, которые когда-то были.
  • 🔥 14
  • 👍 3
  • ❤ 2
Post #251 936
Немного личного: теперь я КМС

Друзья, хочу поделиться новостью. Помимо любимой айтишной работы у меня есть ещё одно серьёзное увлечение: тяжёлое железо 🏋️

Вчера мне официально присвоили разряд кандидата в мастера спорта по становой тяге. Теперь всё по-настоящему: со значком и разрядной книжкой.

Шёл к этому не быстро, но последовательно. Большие цели, будь то спорт, учёба или работа, обычно складываются из маленьких действий, которые повторяешь достаточно долго.

Вчера все эти шаги сложились в результат. Очень рад 🖤

P.S. Ребят, всем кто скидывал мне домашки по практикуму, в ближайшее время обязательно отвечу, был занят.
  • 🔥 55
  • 👏 10
  • 🤩 3
  • ❤ 2
  • 👍 2
  • 😎 1
Post #247 1.14K
За последний год у меня собралась линейка курсов по SQL и Python.

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

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

⭕️ Если пока путаются SELECT, WHERE, GROUP BY и первые соединения, лучше начать с основ.

⭕️ Если ты пока неуверенно работаешь с JOIN, GROUP BY, NULL и базовыми бизнес-условиями, начни с Junior.

⭕️ Если обычные запросы уже даются нормально, но есть сложности с CTE, окнами и ранжированием, тебе подойдёт Middle.

⭕️ Middle+ рассчитан на тех, кому база и окна уже знакомы, но не хватает плотной практики со сложными задачами и объяснением решений на собеседованиях.

⭕️ Python стоит выбрать, когда SQL уже держится, а работа с файлами, функциями и небольшими пайплайнами всё ещё идёт медленно.

⚠️ Если текущие задачи и так решаются уверенно, покупать ещё один курс только из-за скидки смысла нет.

🛒 До 31 августа включительно действуют специальные цены:

• ️SQL основы: 3190 → 2600 ₽
• SQL Junior: 2690 → 2300 ₽
• SQL Middle: 3490 → 3000 ₽
• SQL Middle+ : 4290 → 3700 ₽
•️ Python для DE: 2500 → 2200 ₽

Если нужен последовательный маршрут, есть два комплекта:

• Junior + Middle: 5390 → 4500 ₽
• SQL Pro pack: 8690 → 7300 ₽

Перед покупкой можно посмотреть примеры задач и пройти диагностику. Она поможет выбрать уровень: Выбрать свой маршрут

⚠️ Промокод TG_AUGUST_2026 действует до 31 августа включительно.

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

#курсы
  • 👍 7
  • 🔥 4
  • ❤ 2
Post #246 858
Как посчитать несколько метрик без четырёх подзапросов

Задача не выглядит эффектно, зато постоянно встречается при разработке витрин.

🟫 Допустим, в одной строке за каждый месяц нужно получить:

• общее число заказов;
• число оплаченных заказов;
• долю оплаченных;
• выручку по оплатам.

Похожая задача есть и в моём курсе SQL Middle.

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

☕️ Я обычно использую условную агрегацию через SUM(CASE WHEN ...):

select
date_trunc('month', created_at)::date as month_start,
count(*) as total_orders,
sum(
case
when status = 'paid' then 1
else 0
end
) as paid_orders,
round(
100.0 * sum(
case
when status = 'paid' then 1
else 0
end
) / count(*), 1
) as paid_share,
sum(
case
when status = 'paid' then amount
else 0
end
) as paid_revenue
from orders
group by 1
order by 1;


Каждый CASE решает, какие строки попадут в конкретную метрику. Все метрики считаются в рамках одной агрегации, без отдельных подзапросов и JOIN между их результатами.

Главное, не выносить status = 'paid' в общий WHERE. Иначе неоплаченные заказы исчезнут ещё до агрегации, а доля оплат получится бессмысленной.

✅ В PostgreSQL ту же логику можно записать короче через FILTER:

count(*) filter (where status = 'paid')


В конкретной задаче это аналог:

sum(case when status = 'paid' then 1 else 0 end)


Мне чаще удобнее SUM(CASE WHEN ...): конструкция читается буквально и поддерживается разными СУБД. Но для PostgreSQL вариант с FILTER тоже вполне рабочий.

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

Ставь реакцию:

🔥 - знаю и применяю конструкцию
🤔 - узнал новое

#база_знаний
  • 🔥 14
  • 🤔 8
Post #243 1.04K
Начал ковыряться в n8n ⌨️

Вокруг него много разговоров про ИИ-агентов и автоматизацию всего подряд. Я очень долго смотрел на этот сервис и все никак не мог подступиться. Сейчас захотелось собрать несколько схем руками и понять, как это работает.

🔛 Пока попробовал загрузку текста через webhook, разбиение на части, простое векторное хранилище и поиск по нему. Затем добавил Telegram: отправляешь вопрос, workflow находит подходящие фрагменты и возвращает ответ.

Визуально всё выглядит понятно, но внутри очень много деталей: структура items, связи между узлами, циклы, преобразования и передача контекста. Как раз это и интересно поковырять самостоятельно, и с первого раза сложно. Сервис напоминает конструктор Lego.

Дальше хочу посмотреть, насколько n8n удобен для обычных задач с данными: API, проверки, небольшие загрузки и уведомления об ошибках. Интересно также собрать своего помощника для простых повторяющихся действий. Кажется, что это может упростить отдельные задачи, как в свое время я написал скрипт по сборке файлов для релизов 🎧

Статьи, с которых начал:
• n8n: всё, что нужно знать о сервисе
• n8n: реальные возможности и ограничения
• Плюсы и минусы n8n

Если уже что-то собирали в n8n, накидайте интересных сценариев. Особенно интересны сценарии вокруг данных и обучения.

#материалы
  • 👍 11
  • 🔥 2
  • ❤ 1
  • 🤓 1
Post #241 870
📌 Сегодня хочу дать шпаргалку. SQL-запрос легко прочитать и неправильно представить, как он выполняется.

Мы пишем SELECT первым, хотя движок добирается до него далеко не сразу. Понимание этого порядка часто проверяют на собеседованиях по SQL, аналитике и Data Engineering.

Упрощённый логический порядок выглядит так:

FROM → JOIN → WHERE → GROUP BY → HAVING → оконные функции → SELECT → DISTINCT → ORDER BY → LIMIT


⬇️Какие отсюда следствия:

• WHERE фильтрует исходные строки до группировки;
• HAVING работает уже с результатами группировки;
• оконные функции считаются после WHERE, GROUP BY и HAVING, поэтому обратиться к результату ROW_NUMBER() в WHERE того же запроса нельзя (важно);
• ORDER BY видит алиасы из SELECT, а WHERE обычно ещё не видит.

Например, если нужно оставить только первую строку внутри каждой группы, придётся использовать подзапрос, CTE или QUALIFY, если СУБД его поддерживает.

Но логический порядок ещё не означает, что база физически выполнит операции именно так.

⬆️Оптимизатор может:

• протолкнуть фильтр ближе к чтению данных;
• не читать лишние столбцы и партиции;
• поменять порядок JOIN;
• выбрать Hash Join, Merge Join или Broadcast Join;
• добавить сортировку, Exchange или Shuffle.

По плану выполнения можно заметить полное чтение таблицы вместо нужных партиций, лишний Shuffle, перекос данных, неудачную стратегию JOIN или большую разницу между ожидаемым и фактическим количеством строк.

Поэтому к запросу стоит задавать не только вопрос «правильный ли получился результат?», но и «что движку пришлось сделать, чтобы его получить?».

В PostgreSQL для этого есть EXPLAIN ANALYZE, в Spark — explain() и Spark UI.

Сохраняй и ставь 🔥, если было полезно.

#материалы
  • 🔥 24
  • 👍 3
  • ❤ 1
Post #240 872
🆙 В понедельник, 10 августа, стартует пятый поток DE-практикума.

🧩 Если совсем простыми словами, мы берём сырые CSV-файлы и постепенно превращаем их в нормальный работающий проект: принимаем данные, чистим ошибки, раскладываем по слоям, запускаем обработку и доводим всё до отчёта для бизнеса.

По пути поднимаем Docker-стенд, работаем с PostgreSQL, Spark, Airflow, MinIO и BI. Хочется, чтобы в конце ты действительно понимал, как движутся данные, зачем нужен каждый слой, где искать ошибку и как перезапустить пайплайн, если что-то пошло не так.

Я собирал этот практикум примерно так, как сам хотел бы изучать Data Engineering: на одном цельном проекте, руками и с возможностью задать вопрос, когда застрял. Для меня это давно уже не просто записанный курс. Я постоянно что-то дополняю, переписываю и стараюсь проще объяснять места, на которых участники спотыкаются.

🆕 Буквально вчера полностью обновил модуль по основам Spark. Добавил Spark UI, карту архитектуры и задания по чтению Jobs, Stages, Tasks и Executors.

Теперь можно легко посмотреть, что происходило внутри, как распределилась работа и где искать проблему, если обработка начала тормозить.

В пятом потоке этот модуль уже будет. Участникам предыдущих потоков тоже добавлю обновление в течение недели.

🔎 Заранее знать Spark и Airflow не нужно. Достаточно базы SQL, немного Python и желания разобраться. При этом нужно быть готовым выделять на практикум примерно 6–8 часов в неделю и действительно работать руками.

Если что-то непонятно, будем разбираться вместе. Я много отвечаю участникам и остаюсь на связи до полного прохождения, а не только до формального окончания потока. Мне правда важно, чтобы человек не просто получил доступ, а смог собрать проект до конца.

⏰ Старт 10 августа.

Программа и короткая диагностика

💬 Если интересно, но остались сомнения или вопросы, просто напиши мне: @dim4eg91. Посмотрим на твою текущую базу и решим, комфортно ли тебе заходить сейчас.

#путь_DE
kuzmin-dmitry.ru DE-практикум: соберите ETL-проект от CSV до Airflow и BI Практика для аналитиков и Junior/Middle Data Engineer: Docker, PostgreSQL, Spark, Airflow, DWH и BI. Проверка заданий и поддержка до завершения.
  • ❤ 7
  • 👍 2
  • 🔥 1
Older posts →

About this channel

How can I read @kuzmin_dmitry91 without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Дмитрий Кузьмин | Инженерия данных: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Дмитрий Кузьмин | Инженерия данных have?
Дмитрий Кузьмин | Инженерия данных (@kuzmin_dmitry91) has 1.75K subscribers on Telegram, refreshed roughly every 30 minutes.
Does Дмитрий Кузьмин | Инженерия данных know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →