rzv Data Engineering @rzv_de Channel on Telegram

rzv Data Engineering

@rzv_de


Авторский канал о том, как я понимаю инжиниринг данных. Объясняю термины, best practice, делюсь описанием рабочих задачек. См закрепы

Рассчитан на новичков в DE и инженеров до Senior.

Чат: t.me/+jtQ1tjvNUtwzN2My
По вопросам: @razvodov_de_mentor

rzv Data Engineering (Russian)

Добро пожаловать на авторский канал "rzv Data Engineering"! Этот канал посвящен инжинирингу данных и предназначен для всех, кто интересуется этой темой. Здесь я делюсь своим пониманием инжиниринга данных, объясняю различные термины, рассказываю о лучших практиках и даже делясь описанием рабочих задач. Канал рассчитан как на новичков в области инжиниринга данных, так и на опытных инженеров до уровня Senior. Если вы хотите узнать больше о DE или развить свои знания в этой области, то этот канал - отличное место для этого. Присоединяйтесь к нам, чтобы быть в курсе всех новостей и обсуждений в мире инжиниринга данных! Для общения и задавания вопросов также доступен наш чат: [ссылка на чат]. По всем вопросам вы также можете обращаться к ментору канала @razvodov_de_mentor. Не упустите возможность расширить свои знания и присоединяйтесь к каналу "rzv Data Engineering" прямо сейчас!

rzv Data Engineering

04 Feb, 06:49


#анонс

Boosty-цель выполнена — стриму с разбором резюме быть

В субботу 08.02.25, в 19:00 мск, я проведу стрим на твиче на 2.5-3ч.

🔸 Сильное резюме почти гарантирует возможность дойти до тех. собеса и показать свои навыки. Если ты не ищешь работу сейчас, оно добавит спокойствия на случай резких перемен в жизни (увольнение, переезд и т.д.). Или поможет улучшить условия труда и повысить ЗП.

🔸 Присылай своё резюме заранее, буду проходить по стопке "снизу-вверх", разбирая очередь. Закинуть на стриме тоже можно будет, но я не обещаю успеть всё. Планирую до 10 минут на 1 резюме, почти наверняка в "одностороннем режиме", без диалога.

Стрим будет записан и выложен на ютуб.

🔸 Почему моё мнение может быть полезным:
. HR сами пишут мне в личку, даже когда я в пассивном поиске с фильтром "от 400к на руки"
. через меня в роли ментора прошло более 50 человек. Скину в комменты обратную связь от некоторых из них по результатам доработки резюме
. в 2024 я получил 4 Sr. DE оффера на 500к+ на руки (в том числе с релокацией на Кипр)
. сам отсобеседовал 10+ человек на позиции middle, senior

UPD: приём резюме закрыт

Моё актуальное резюме всегда доступно здесь

rzv Data Engineering

03 Feb, 08:58


#вести_с_полей

Напоминалка про NULL в sql

Null не содержит значения (мы не знаем, какое значение атрибута было "в том месте и в то время"),
но хранит тип данных.

На продакшене, если добавляешь новую колонку "на будущее" или гармонизируешь данные из разных источников, вместо
select ...
, null as new_int_col
, null as new_date_col
, null as new_ts_col

стоит писать
select ...
, (cast null as integer) as new_int_col
, (cast null as date) as new_date_col
, (cast null as timestamp with time zone) as new_ts_col

Иначе жди проблемы интеграций "ниже по потоку" или при union all'ах.

p.s. Ну и помни, что в SQL boolean может иметь три значения, и null != False != True :)

rzv Data Engineering

18 Jan, 15:00


Привет, делюсь папкой дата инженерных каналов с интересным контентом.
Заходи к нам на вечеринку по ссылке: https://t.me/addlist/a1B07iwrPxUxNWIy

rzv Data Engineering

17 Jan, 14:04


#реклама

Праздничные выходные заканчиваются, начинаются большие возможности!

Уже есть опыт работы с хранилищами данных, но хочешь прокачать скилы и открыть новые карьерные горизонты? Приглашаем на ИТ-интенсив в Открытые школы Т1!

За месяц ты бесплатно получишь новые знания, практический опыт и шанс продолжить карьеру в крупнейшей российской ИТ-компании Т1!*

А также:

🧩 бесплатное обучение в гибком формате: по вечерам, онлайн, из любого города РФ и РБ;

🧩 материалы от HR для прокачки резюме и подготовки к интервью в Т1;

🧩 знакомство с ИТ-командой, погружение в культуру, проекты и процессы;

🧩 поддержка опытных преподавателей и карьерный фаст-трек до мидла в Т1 для выпускников;

🧩 реальный шанс получить оффер в Т1 и работать в аккредитованной ИТ-компании с современным техстеком и классными бонусами: ДМС, удаленка и крутые офисы, спорт и обучение, митапы и ИТ-конференции, программы признания и развития для твоего роста.

Сделай первый шаг в будущее — подай заявку до 10.02!

*По выручке, по версии RAEX и CNews Analytics 2023.

Реклама. ООО «Т1» ИНН: 7720484492. Erid: 2SDnjdg47fi

rzv Data Engineering

17 Jan, 08:50


#поразмыслим

Проблема "дрейфующих" первичных ключей при объединении данных из разных систем

🔸 Допустим, есть 10 разных однотипных источников о клиентах, из которых нужно получить по 1 записи о каждом "реальном" клиенте.

Для решения такой задачи есть процессы "матчинга" и "мёржинга". В первом случае сопоставляем строки между собой и формируем "кластер" записей. Во втором — схлопываем в одну "золотую" запись, выбирая самый полный набор атрибутов из самых достоверных источников. Я уже писал выше про ``splink`` как один из python пакетов, на которых можно такое реализовать.

🔸 Но что делать с ключами? Если выбирать "главную" запись в кластере и делать, например, расчёт хэша на основе её хэша, на первый взгляд всё хорошо.

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

🔸 А что если эта "главная" запись удалится, а остальные — продолжат формировать кластер? Как сохранить итоговый ключ, чтобы сохранить историю изменений?

И на основе чего его можно считать, если у нас нет надёжного набора бизнес-ключей, по которым мы можем гарантировать, что эти записи — об одном человеке. И запись из любого источника может удалиться или "перенестись" в другой кластер при изменении правила матчинга.

Более подробный пример будет в комментах внутри

Ставь 🐘 или ⭐️, если хочешь больше сеньорных постов

rzv Data Engineering

13 Jan, 10:08


#реклама

Разбираем тестовое задание в Альфа Банк на позицию Junior Аналитика данных

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

Чтобы попрактиковаться в этом, приходите на бесплатный вебинар, где будем разбирать реальное тестовое задание, которое дают аналитикам в Альфа Банке.

Что будем делать на вебинаре:
• Напишем сложные SQL-запросы для банковских данных;
• Вспомним, как правильно использовать оконные функции;
• Узнаем, как создавать разметку, из чего она состоит и для чего она нужна;
• На реальных данных проведем когортный анализ и сделаем выводы;
• Расскажем, как доставать инсайты из данных.

Вебинар проведет Денис Иванов, ведущий продуктовый аналитик

🕗Встречаемся 14 января в 19:00

Зарегистрироваться на бесплатный вебинар

rzv Data Engineering

13 Jan, 08:55


#термин_дня

Версионирование данных при работе с дата лейком

Листая ленту, наткнулся на любопытный инструмент: https://projectnessie.org/

Работает с Iceberg и даёт возможность работать с данными как с кодом:
. отводить отдельные ветки для отладки фичей
. версионирование
. транзакционное изменение пачки файлов (acid-like)

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

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

rzv Data Engineering

09 Jan, 07:00


(само-) #реклама

Занимай активную позицию по отношению к карьере в самом начале 2025-го!

🎆 Для новых и возвращающихся подписчиков делюсь промо-ссылкой на бусти чат. В нём помогаем друг другу развиваться в сфере дата инжиниринга с самых разных уровней -- есть что и с кем обсудить и "вкатунам", и сеньорам, и всем между ними)

🎁 Первая сотня шустрых людей получит доступ на 2 дня ко всем 19 тредам чата (на картинке показана только часть).

☕️ Взгляни на историю сообщений и текущее общение, почувствуй атмосферу и реши, хочешь остаться с нами или нет ;)

>>> Успей перейти по ссылке

rzv Data Engineering

31 Dec, 15:27


Итоги года 2024

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

Это канал про DE, поэтому держи немного сухих данных.

🔸 Сводка за год:
Подписчиков: 1368
Постов: 253
Среднее кол-во просмотров: 866.5
Максимум просмотров: 4852
Рекорд постов за день: 15 (2024-01-21)

🔸 Топ тегов:
#термин_дня: 38
#зачем_нужно: 25
#вести_с_полей: 13
#поразмыслим: 12
#реклама: 11 (спасибо за поддержку)

🔸 Самые популярные серии постов за год (по просмотрам):
https://t.me/rzv_de/228
https://t.me/rzv_de/257
https://t.me/rzv_de/175
https://t.me/rzv_de/241
https://t.me/rzv_de/244
https://t.me/rzv_de/183
https://t.me/rzv_de/233
https://t.me/rzv_de/213
https://t.me/rzv_de/248
https://t.me/rzv_de/224

Также около 15 человек получилось довести до оффера (тыкаю их в переписке, чтобы внесли инфу в стату и попали в дашборд, а то никто ж не поверит), нескольким десяткам людей помог консультациями, вырастил закрытое бусти сообщество до 60 человек, дважды сменил работу с ростом ЗП х3.5

p.s. а вообще, в начале пути выпустил много маленьких полезных постов, пролистай на праздниках -- меню "сэндвич", "go to the beginning" ;)

rzv Data Engineering

24 Dec, 06:41


REPLACE TABLE в Delta lake вместо DROP + RECREATE 2/2

🔸 Какое решение есть у delta table? Как и во многом другом, современные инструменты дают простой интерфейс для решения проблем, а сами делают тяжёлую работу под капотом. Будто говорит: "Хочешь пересоздать таблицу? Так именно это и напиши"

REPLACE TABLE table_name
as select * from ...


Помимо того, что поддерживается одновременный доступ на чтение для многих запросов (concurrently), операция выполняется в транзакции (см. ACID), ещё и история сохраняется — можно откатить к предыдущей версии одной командой (см. time travel in Delta tables).

В dbt, например, включается единственным конфигом на весь проект: on_table_exists: replace

В хорошее время живём)

p.s. Delta формат открытый и бесплатный, можно использовать уже завтра без доплаты за остальной Databricks

rzv Data Engineering

24 Dec, 06:41


#зачем_нужно #вести_с_полей
REPLACE TABLE в Delta lake вместо DROP + RECREATE 1/2

🔸 Дата инженеры работают с большими и очень большими данными, поэтому для хранения и обработки всё меньше подходят CSV и JSON. Даже Parquet и ORC заменяются Hudi, Iceberg и Delta таблицами. С последними я пилю текущий проект на работе, поэтому иногда буду писать о встреченных фишках.

🔸 Например, в случае пересчёта таблицы есть несколько обычных стратегий:
. drop + create, пересоздать объект с нуля, если есть несовместимые изменения схемы данных
. insert overwrite partition, если изменилась логика или обновился источник и можем пересчитать по партиции за раз
. create + rename + drop, создать рядом промежуточную таблицу, прогрузить её данными, а потом "свопнуть", т.е. поменять местами с текущей таблицей — актуально для тяжёлых витрин с непозволительностью даунтайма для технических работ

🔸 Однако каждый из этих способов обладает своими недостатками:
. в первом случае будет даунтайм на период просчёта, и, в случае ошибки создания новой версии, пользователи и пайплайны будут заблокированы
. во втором случае запросы над несколькими партициями сразу могут возвращать несогласованные данные до окончания операции просчёта; или объект блокируется целиком на время всего пересчёта -> снова даунтайм
. третий подход выглядит хорошо (и может быть вариантом реализации online schema evolution), но редко встречается "из коробки" и его приходится писать, например, в виде кастомной материализации в dbt

rzv Data Engineering

19 Dec, 07:03


Может, с такой целью будет интереснее)

А Ask me Anything для канала ближе к новому году проведу просто так

rzv Data Engineering

18 Dec, 18:15


Напоминаю, что закрытый тестовый стрим будет завтра, 19 декабря в 19:00 мск

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

rzv Data Engineering

16 Dec, 10:22


Встречайте, инфографика

Возможно тебе будет интересно заглянуть за ширму, что там у нас внутри происходит. И если кто-то из знакомых или ты сам ищешь ментора по DE, пиши в личку. Если не уверен(а), нужен ли тебе ментор, -- тоже. @razvodov_de_mentor :)

Активность в чате и публикации в закрытых каналах: https://datalens.yandex/vhix6u25akgwi
Офферы, полученные с помощью меня и сообщества: https://datalens.yandex/l5r0iby4zpgg8

Upd: допилил немного собирающий стату код и выложил в открытый доступ. Дашборд по офферам собирается на основе гугл форм
https://github.com/LexxaRRioo/tg-private-ch-stats-to-sheets-export
Ставь звёзды ⭐️, используй себе на пользу, всё дела

rzv Data Engineering

16 Dec, 08:59


Анонс: В четверг, 19 декабря в 19 мск, запускаю тестовый стрим для подписчиков на бусти.
Пообщаемся в формате Ask me Anything. В качестве площадки 99% будет Twitch

Для участия можно выбрать любой уровень, смотри по наполнению и самостоятельно определи для себя самый полезный
https://boosty.to/rzv_de

Если кто недавно на канале, о чём меня можно спросить (ЦА -- как интересующиеся сферой, так и уже работающие в DE уровнем до Sr):
. как перейти в сферу дата инжиниринга с нуля или из смежных профессий
. что из инструментов популярно в России и почему
. лёгкие и средние архитектурные вопросы
. что-то по работе или собесам
. всё что угодно другое

Не обещаю, что на всё отвечу, но постараюсь прочесть каждый вопрос)

p.s. Когда заполним шкалу до конца, проведу публичный стрим часа на 3-4 для всех

rzv Data Engineering

13 Dec, 12:49


🔴 ROADMAP V2.0 для Data Engineer!

Иди прямо по списку, чтобы стать Data Engineer!

➡️ ROADMAP

Кликай на ссылку снизу:
0.
Деньги
1.
Кто такой Data Engineer
2.
Курсы
3.
Github / Git
4.
Linux / Terminal
5.
Data Warehouse
6.
Нормальные формы
7.
Data Vault (Hub - Satellite - Link)
8.
Docker
9.
Hadoop
10.
Airflow
11.
Greenplum
12.
ClickHouse
13.
Spark
14.
dbt (data build tool)
15.
Apache Kafka
16.
Pet Project
17.
Теоретические вопросы c собеседований
18.
Резюме и Работа
19.
Рабочие кейсы
20.
Полезные ссылки

📺 Кто я и как попал в IT?
СМОТРИ интервью со мной!

🅱️🩸🩸🩸🩸
Сколько ты зарабатываешь? | Где лучше работать? | Че спросят на собесе?

Авторы Roadmap:
Евгений Виндюков
😀 Telegram канал
📺 Youtube канал

Владимир Шустиков
💬 Telegram канал
📺 Youtube канал

Алексей Разводов
💬 Telegram канал
📺 Youtube канал

rzv Data Engineering

13 Dec, 12:49


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

Моя часть -- про DBT (data build tool), структурировал и выгрузил знания за почти год плотной работы с этим тулом. Остальные лавры кидай другим двум авторам)

Пользуйся, предлагай правки в pull request'ах, рассказывай всем друзьям и близким. Ну и измени свою жизнь к лучшему, если ещё не)

🔸 А если даже примерно не представляешь, что такое dbt, смело кликай на раздел и начинай погружение. Как раз для тебя и писал эту часть роадмапа. Всё по порядку, через практику и с разбором ровно на нужную глубину, всё как я люблю.

rzv Data Engineering

09 Dec, 11:51


#реклама

Станьте инженером данных с нуля за 5 месяцев, обучаясь на реальных задачах бизнеса.

Основная проблема обучений – оторванность от задач реального бизнеса. На курсе учился складывать 2+2, а на работе – сразу отправляют считать интегралы.

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

Обучение охватывает весь стек, который нужен специалисту: SQL, Python, Metabse, Linux, Docker, Airflow, Clickhouse, Hadoop и Spark. А также готовит к любому собеседованию – в курс включены тестовые задания, пробные интервью (технические и с HR) и многое другое.

С трудоустройством поможем, а на VIP тарифе преподаватели и HR спроектируют вам персональный трек обучения и за руку доведут до оффера. Часть стоимости курса вы оплачиваете только, когда найдёте работу.

Еще успеваете записаться в текущий поток
По промокоду RZV
дарим скидку 12%

rzv Data Engineering

09 Dec, 10:30


#зачем_нужно

Типы timestamps в Data Engineering 1/3

🔸 Сегодня разберём такую базовую, но важную штуку как timestamps в данных. Казалось бы, что тут сложного – просто метки времени. Но их бывает несколько видов, и путаница между ними может создать серьёзные проблемы.

В работе с данными встречаются разные timestamps. Самые частые – это created_at* (когда данные появились) и modified_at (когда изменились). В Data Warehouse часто увидишь loaded_at (загрузка в хранилище) и processed_at (обработка).

Реже, но в особых случаях пригодятся sent_at (отправка) и received_at (получение). Они важны в распределённых системах, где критична точность отслеживания движения данных или есть существенные задержки в передаче.

* конечно же, названия полей могут быть какими угодно, улови суть

🔸 Давай рассмотрим простой пример. У тебя мобильное приложение, которое собирает данные о действиях пользователей. Вот как будут различаться timestamps:

WITH user_actions AS (
SELECT *
FROM (VALUES
('action1',
'2024-01-01 12:00:00'::timestamp, -- created_at (пользователь нажал кнопку)
'2024-01-01 15:30:00'::timestamp, -- sent_at (телефон был офлайн 3.5 часа)
'2024-01-01 15:30:02'::timestamp, -- received_at (задержка сети 2 сек)
'2024-01-01 15:35:00'::timestamp -- processed_at (очередь обработки 5 мин)
)
) AS t(action_id, created_at, sent_at, received_at, processed_at)
)
SELECT * FROM user_actions;

Видишь разницу? Если использовать только processed_at, можно подумать, что пользователь бездействовал 3.5 часа. А на самом деле это была проблема связи.

rzv Data Engineering

09 Dec, 10:30


Типы timestamps в Data Engineering 2/3

🔸 Особый случай – timestamps в SCD2 таблицах. Created_at надёжно показывает, когда появилась запись, а valid_from/valid_to отвечают за историчность данных. Важно сохранять обе группы дат. Смотри пример:

WITH source_changes AS (
SELECT *
FROM (VALUES
(1, 'Старый адрес', '2024-01-01 10:00:00'::timestamp),
(1, 'Новый адрес', '2024-01-01 15:00:00'::timestamp)
) AS t(user_id, address, created_at)
),

-- Храним обе группы дат
complete_approach AS (
SELECT
user_id,
address,
created_at, -- когда создали запись
created_at as valid_from, -- когда версия стала активной
COALESCE(LEAD(created_at)
OVER (PARTITION BY user_id ORDER BY created_at) - interval '1' second
, '9999-12-31'::timestamp) as valid_to -- когда версия стала неактивной
FROM source_changes
)

SELECT * FROM complete_approach
ORDER BY created_at;

Зачем хранить обе группы дат:
* Created_at нужен для аудита – когда физически появилась запись
* Valid_from/valid_to показывают период действия версии
* При откате изменений или исправлении ошибок в истории у нас будет полная картина

rzv Data Engineering

09 Dec, 10:30


Типы timestamps в Data Engineering 3/3

🔸 И ещё один важный тип – бизнес-даты. В отличие от технических timestamps, они отражают реальные события: дата открытия счёта, дата рождения клиента, дата блокировки аккаунта. Их используют для бизнес-аналитики и часто джойнят с техническими датами для отслеживания задержек между реальным событием и его появлением в системе.

Бизнес-даты особенно важны в регуляторной отчётности и compliance, где нужно чётко различать, когда событие произошло в реальности и когда оно было зафиксировано в системе.

И вопрос тебе: какие самые неочевидные баги в своей практике ты находил(а) из-за путаницы с timestamps? Делись в комментариях!

rzv Data Engineering

06 Dec, 18:11


Ещё одна искренняя рекомендация от меня, сам регулярно читаю посты.

Задумывались, как DE выглядит со стороны?

Согласитесь, термины из мира распределенных систем и архитектуры данных в повседневной жизни не всегда кажутся большинству людей какой-то тарабарщиной, ну или mumbo jubo, если хотите проникнуться англицизмами.

🔸Kafka для меня — давно распределенная платформа обмена сообщениями; ассоциация с произведением «Превращение» автора Ф. Кафки отходит на второй план.
А вообще, представьте, как обсуждаете с коллегами параллели в архитектуре Кафки и мотивы отчуждения в его произведениях! Без хорошего английского тут не обойтись.

🔸 Shard для нас — фрагмент распределенных данных. В обычном английском (внезапно) shard переводится как осколок/обломок целого. Интересно порассуждать, как принцип "разделяй и властвуй" работает в базах данных и в жизни.

Вот уже пять лет пытаюсь свыкнуться с мыслью о том, что
🔸Replica на человеческом — не просто копия данных на другом сервере, но ещё и точная подделка произведения искусства или бренда. Вот вам вариант досуга на вечер: сверкать эрудицией, щеголяя острыми нюансами репликации баз данных и проблем подделок в искусстве.

Слабо провести аналогию между сложными зависимостями в data pipeline и хитросплетениями семейных связей в «Игре престолов»? Должно быть, нет; потому что
🔸Lineage (история преобразования данных в виде графа) на самом деле родословная, генеалогическое древо.

Надеюсь, я вдохновил Вас заглянуть на Peachy English, где каждый IT-специалист найдет что-то полезное про CV и Interview, релокацию и жизненные идиомы.

Да-да, даже если «несмешно» ты все еще переводишь как ahahan't, а фраза «S как доллар» точно описывает твой уровень английского.

rzv Data Engineering

06 Dec, 12:05


Рубрика "что ещё можно почитать, пока нет постов на этом канале".

Рекомендую дружественный ресурс.

DataEngineers.pro — это одна из первых русскоязычных платформ для всех, кто хочет развиваться в сфере Data Engineering. Здесь вы найдёте:

Рекомендованные курсы для новичков.
Информацию о ключевых инструментах: SQL, Spark, Airflow и других.
Библиотеку материалов: статьи, книги, видео и подкасты.
Раздел вакансий для поиска работы.
Каталог менторов, готовых помочь вам на пути к успеху.

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

rzv Data Engineering

22 Nov, 14:00


#зачем_нужно

Проблемы и решения в очистке данных 4/4


🔶 Нормализация unicode символов
 
translate(column, 'áéíóúàèìòùãẽĩõũâêîôûäëïöüçñ', 'aeiouaeiouaeiouaeiouaeioucn')

regexp_replace(column, '[^\x00-\x7F]+', '') /* удаление не ASCII символов */

Рассказать в следующем посте про colation настройки БД (или почему иногда сортировка одних и тех же данных может выдавать разный результат) ? :)

🔶 Конвертация часовых поясов
 
select timestampz_column at time zone 'Europe/Moscow'

coalesce(
try_cast(timestamp_column as timestamp with time zone),
timestamp_column::timestamp at time zone 'UTC'
) /* если не всегда указана временная зона */


🔶 Обработка спецсимволов в текстовых полях
 
regexp_replace(column, '[^a-zA-Z0-9\s]', '') /* только буквы, цифры и пробелы */

translate(column, '[]{}()*#$%@!?+=/\|', '') /* удаление конкретных символов */


🔶 Приведение булевых значений к стандартному виду
 
case
when lower(column) in ('1', 'yes', 'true', 'y', 't') then true
when lower(column) in ('0', 'no', 'false', 'n', 'f') then false
else null
end as bool_column


Ну что, как тебе формат? Голосуй реактами и комментами, если хочешь больше такого

rzv Data Engineering

21 Nov, 14:00


#зачем_нужно

Проблемы и решения в очистке данных 3/?

🔶 Даты из далёкого будущего или прошлого
 
case
when date_column between '1900-01-01' and '2100-12-31'
then date_column
else cast(null as date)
end as valid_date /* уточняй, как должно быть
по бизнес-требованиям. иногда даты из средне-далёкого
будущего это ок, например "плановая дата закрытия ипотеки" */


🔶 Объединить значения из нескольких строк в один массив

select key,
string_agg(values, ',')
from ...
group by key


🔶 Полные дубли (совпадают все поля)
 
select distinct col1, col2, col3
from table

/* или */

select col1, col2, col3
from table
group by col1, col2, col3

Вопрос со звёздочкой*: какая разница между distinct и group by в этом примере?

🔶 Неполные дубли (различаются технические поля)
with prep_cte as (
select col1, col2, business_key, updated_at,
row_number() over (
partition by business_key
order by coalesce(updated_at, '1900-01-01') desc
) as rn
from table
)
select * from prep_cte
where rn = 1
/* оставляем последнюю версию строки по каждому бизнес-ключу */


А здесь было что-то, что пригодится уже завтра на работе?

rzv Data Engineering

20 Nov, 15:39


Альтернативная обложка для поста про NULL'ы

rzv Data Engineering

20 Nov, 15:20


#зачем_нужно

Проблемы и решения в очистке данных 2/?

🔶 Значение "по умолчанию" для отсутствия данных в виде пустой строки или "Nan", когда для обработки нужен NULL
case when trim(lower(column)) in (
'', 'null', 'none', 'n/a', 'na', '-',
'#n/a', '#н/д', '(empty)', 'undefined'
) or column ~ '^\s*$' /* только пробелы */
then null
else column
end as clean_column


🔶 Разный тип данных при union/union all или колонок из условия on в join
case when numeric_col ~ '^\d+(\.\d+)?$' 
then cast(numeric_col as decimal(18,2))
else null
end /* для последующих join по числовым полям */


cast(num_id as varchar(20)) as num_id /* для join, 
где с одной стороны поле varchar(20), а в другой -- числа */


union example:
select cast(id as varchar) as id, name from table1
union all
select id, name from table2 /* приводим к более широкому типу */


case when try_cast(date_field as date) is not null 
then try_cast(date_field as date)
else try_cast(date_field as timestamp)::date
end /* для разных форматов дат */


🔶 Вставка в таргет-таблицу NOT NULL поля из источника, где значение может отсутствовать
coalesce(column, 'default') as column 


🔶 У одного из объектов, объединяемых через union/union all, не достаёт колонки
cast(null as [data_type]) as column /* null может быть разных типов */


🔶 Разъединить одну колонку на несколько
split_part(full_name, ' ', 1) as surname,
split_part(full_name, ' ', 2) as name /* наивный подход,
для каждого отдельного случая может быть сильно сложнее, вплоть до регулярок */


🔶 Объединить несколько колонок в одну
concat_ws(' ', nullif(address_line_1, ''), nullif(address_line_2, '')) as address


А в этом посте уже было что-то новое? Делись в комментах

rzv Data Engineering

19 Nov, 14:46


Эксперимент — серия постов будет выходить средними кусочками несколько дней подряд

#зачем_нужно

Проблемы и решения в очистке данных 1/?

При загрузке данных из исходных систем мы почти всегда сталкиваемся с "грязными" данными - опечатки, разные форматы, технические ошибки. Если не обработать такие случаи, таблицы перестанут джойниться или будут выдавать мусор на выходе (в BI, отчётах и пр.).

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

🔶 Название поля не соответствует naming convention в DWH
column as new_column

Лучше хотя бы на raw слое оставить исходные названия колонок для lineage и traceability. И старайся не множить сущности, где возможно, приводи к единому стилю (naming convention) и называй одинаковые параметры одинаково, а разные — по-разному.

🔶 Формат даты

try_cast(date_column as date) /* для безопасного приведения */

to_date(date_string, 'YYYY-MM-DD') /* если известен формат */

case when date_column ~ '^\d{4}-\d{2}-\d{2}$' then cast(date_column as date) end /* с валидацией */


🔶 JSON, который нужно распарсить и разложить по колонкам

case when is_valid_json(json_column) then /* проверка валидности */
json_value(json_column, '$.field_name'),
json_query(json_column, '$.contacts[*].phone'), /* массив */
json_value(json_column, '$.address.city'), /* вложенный объект */
(select string_agg(value, ',')
from json_table(json_column, '$.tags[*]' columns (value varchar path '$'))
) as tags /* массив в строку */
end

Не забывай обрабатывать случаи с пустыми JSON'ами и массивами.

🔶 Вручную заполняемые поля "перечисляемого типа", которые нужно привести к одному виду

Использовать нечёткое сопоставление, например splink на python, или вручную заполненный маппинг значений, предварительно приведённых к trim(upper(replace(column, ' ', ''))) или другому подобному формату.

Написание запросов а-ля lower(col) like '%sub%string%' плохо масштабируется и зачастую приводит к неожиданным результатам (когда под шаблон начинают попадать "не те" категории).

rzv Data Engineering

28 Oct, 12:12


#реклама

Обучаем IT-специалистов и берём в команду ⚡️


Лучшим участникам предложим оффер в Т1 — крупнейшую по выручке ИТ-компанию страны по версии RAEX и CNews Analytics 2023 🔝.

Зачем участвовать?


🔹 Уникальный рыночный опыт. Т1 одни из первых на рынке, кто внедряет технологии для управления данными.

🔹 Попасть в число лучших. Проекты Т1 ежегодно получают лучшие награды на ИТ-конкурсах: Global CIO, Национальная банковская премия и др.

🔹 Поддержка. Тебя ждёт команда опытных профессионалов, которые помогут расти и развиваться.

Выбирай:

📁 аналитик платформы данных (DWH)

🖥 разработчик платформы данных (DWH)


От тебя нужен только опыт работы от 6 месяцев в проектах разработки хранилищ данных и желание попасть в команду Т1.

Быстрое обучение: 1 месяц

📱 Гибкий формат: онлайн по вечерам (от 8 часов в неделю на вебинары и практику)

Подавай заявку до 5 ноября!

Реклама. ООО «Т1» ИНН: 7720484492. Erid: 2SDnjcdR3XH

rzv Data Engineering

28 Oct, 07:41


#термин_дня

Кратко о видах Executor в Airflow

Экзекьютор это компонент Airflow, который определяет, где и как будет запущен таск дага.

На момент написания поста (airflow 2.10) есть 4 основных варианта:
🔸 SequentialExecutor — включён по умолчанию, очень медленный, простой как палка. Плох даже для локальных дев-стендов и пет-проектов.

🔸 LocalExecutor — работает как часть Scheduler'a и не требует отдельных сервисов-воркеров. Поддерживает параллельный запуск, отлично подходит для локальной отладки и небольших дев-стендов.

🔸 CeleryExecutor использует Redis или RabbitMQ в качестве бэкенда для координации тасков между пред-настроенными воркерами. Отлично подходит для большого объёма коротких тасок. Также есть полезный UI flower для мониторинг, который можно запустить отдельным процессом. По моему опыту, Celery воркеры обычно запускаются на виртуальных машинах.

Ограничения: все воркеры должны быть строго одинаково настроены, включая набор и версии python пакетов и всяких CLI, синхронизацию DAGS_FOLDER (обычно через гит). Есть возможность обойти, но это сильно усложнит поддержку.

🔸 KubernetesExecutor — запускает отдельный под в K8s для каждой таски, можно выделить больше ресурсов для тяжёлых задач. Под уничтожается после окончания работы таски.

Этот режим добавляет накладные расходы (десятки секунд) на запуск и остановку подов, что лучше подходит для длинных и редко запускаемых задач. Серия мелких тасок будет тормозить. Зато можно высвобождать ресурсы и не платить 24/7 за простой воркеров.

🔸 И, как со всем в Airflow, можно написать свой Executor. Но должна быть уверенность, что задачу не получится решить через стандартные.

Для дочитавших бонус: с v2.10 можно сконфигурировать несколько экзекьюторов параллельно и назначать для каждой таски свой тип — или Celery, или K8s. Есть даже гибриды вида CeleryKubernetesExecutor, но они не рекомендуются командой Airflow.

Напиши в комментах, какие у тебя весёлые истории встречались с K8s экзекьютором, если используешь на проде :)

rzv Data Engineering

27 Oct, 14:59


Решил, пора. Ищу ассистента для помощи в управлении сообществом. Читай вакансию и откликайся по ссылке:
https://forms.gle/GViJ4WYD5JnjKvTu8

rzv Data Engineering

25 Oct, 05:49


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

Он крутой инженер "старой закалки", который в любой непонятной ситуации читает исходный код.

https://t.me/GreenplumSQLClub

rzv Data Engineering

02 Oct, 09:42


#видео #моксобес

Ты знаешь, что с этим делать

-> Ссылка на видео (youtube)
-> Ссылка на видео (vk video)

rzv Data Engineering

25 Sep, 12:02


#зачем_нужно

Кастомные материализации в dbt: мощный инструмент или поворот не туда? 1/2

🔸 dbt предоставляет стандартные материализации (table, view, incremental, ephemeral), которые покрывают большинство сценариев. Но иногда возникает потребность в чем-то особенном. Как и в airflow, в dbt можно переопределить всё что угодно и написать свою имплементацию Х, подложив код в папку с проектом.

🔸 Когда стоит задуматься о кастомных материализациях?
* Специфические требования к производительности
* Уникальные особенности вашего DWH
* Сложная бизнес-логика, выходящая за рамки стандартных подходов
* Необходимость в повторяющихся паттернах, которые не покрываются существующими материализациями. Например, когда при full-refresh нужно добавить промежуточные шаги для backfill'a или хочется добавить возможность скастить поле в table без пересчёта.

🔸 Важно помнить: кастомные материализации гарантированно усложнят проект, а полезными не факт, что будут. Перед их внедрением задай себе несколько вопросов:
* Действительно ли стандартные материализации не справляются с задачей? Может, я "не умею их готовить"?
* Можно ли решить проблему с помощью post-hooks или pre-hooks?
* Готова ли команда поддерживать кастомный код в долгосрочной перспективе?

🔸 Когда лучше воздержаться от кастомных материализаций:
* Команда не имеет глубокого понимания dbt и SQL или её воротит от одной мысли поддержки pascal-like скриптов
* Проект часто мигрирует между разными типами баз данных
* Нет четкого плана по поддержке и обновлению кастомного кода
* Кастомизация требуется только для одной или двух моделей

rzv Data Engineering

25 Sep, 12:02


Кастомные материализации в dbt: мощный инструмент или поворот не туда? 2/2

Пример базовой кастомной материализации my_project/macros/my_materialization.sql:
{% materialization custom_table, default %}
{%- set target_relation = this.incorporate(type='table') %}

{{ run_hooks(pre_hooks) }}

-- в main нужно обязательно сформировать код, который отправится в `target/compile` и `target/run` директории для этой модельки
{% call statement('main') -%}
{{ create_table_as(target_relation, sql) }}
{%- endcall %}

{{ run_hooks(post_hooks) }}

{{ return({'relations': [target_relation]}) }}
{% endmaterialization %}


Тогда модель my_project/models/my_model.sql будет выглядеть так:
{{ config(materialized='custom_table') }}

select *
from {{ source("default", "my_raw_model") }}


В реальных сценариях нужно добавить специфичную для адаптера логику (например, через макросы и adapter-dispatch) или дополнительные шаги обработки. Изучи реализации, поставленные "из коробки", прежде чем писать своё :)

А тебе приходилось сталкиваться с ситуациями, когда кастомные материализации реально спасли проект? Или, может быть, наоборот, усложнили его до невозможности? Поделись опытом в комментариях!

rzv Data Engineering

15 Sep, 14:52


#видео #моксобес

Шестой выпуск серии мок-собесов на youtube

-> Ссылка на видео (youtube)
-> Ссылка на видео (vk video)

rzv Data Engineering

07 Sep, 09:42


Александр вёл нешуточную борьбу с техническими неполадками.

Часть стрима провели в онлайне, но потом он всё же упал. Ссылка на то, что удалось спасти, в комментах.

Разошлись немного ожидания с Александром по формату, оказалось что это не совсем интервью.

Возможно проведу часть два так, как я сам это вижу. Stay tuned

rzv Data Engineering

06 Sep, 15:41


Завтра, в субботу 7 сентября, в 12:00 мск будет стрим-интервью с @digitalberd

Расскажу о своём пути, почему и как пришёл в менторство и в инженерию данных, затронем ещё пару тем.

https://www.youtube.com/live/Zh5WGo18-L8?si=OicFyIX2nr6VFHmE

Стрим начинается!

rzv Data Engineering

02 Sep, 18:03


#видео #моксобес

Подвёз контент под вечер. Пятый выпуск серии мок-собесов на youtube

-> Ссылка на видео (youtube)
-> Ссылка на видео (vk video)

rzv Data Engineering

30 Aug, 10:29


#поразмыслим

С какими проблемами может столкнуться дата инженер, выполняя изменение схемы данных на проде (schema evolution)?

Как эти проблемы можно решить на проекте?

Ограничимся RDBMS MPP классом систем