Telegram Web
Собранные грабли на пути интеграции Spark + MinIO + Jupyter + Airflow в Docker Compose 8/8

🔸 Вместо заключения

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

Но это всё получается преодолеть, особенно если отбрасывать в сторону сопротивление и читать официальную документацию. Ну и форумы, а не только общаться с GPT — объяснения живых людей пока на порядок надёжнее и понятнее потуг ИскИн'а (AI).

Самое забавное, что даже использование IaC технологий вроде Docker не гарантирует воспроизводимости. Потому что доступ к репозиториям могут закрыть, сервис может переехать на другой хост, кто-то может грязно пользоваться SemVer и пихать обновления в ту же версию или эту версию в принципе могут удалить из индекса, и она перестанет определяться по сети. Ну и кто-то наверняка заметил, что в одном из прошлых постов у пайтон пакетов я закрепил версию только для pyspark ;)

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

У меня пока всё, но не прощаюсь. А тебе знакома боль настройки локального (или даже продакшен) окружения? Делись историями в комментах ;)
#реклама #рекомендация

Про семантический слой и LLM-боты к данным 1/2

🔸 В последнее время всё чаще мелькают дискуссии вокруг Self-Service BI и чат-интерфейсов к данным. Мол, скоро забудем дашборды и будем кверить данные прямо в чате.
Регулярно встречаю статьи от Хабра до Медиума, где кто-то показывает, как легко можно сделать Text-to-SQL агента и общаться с базой на естественном языке. Обычно в качестве примера демонстрируют, как модели ловко справляются с запросом в духе «Выручка за последний год».

Но в реальной жизни никто не приходит в БД с вопросом “Посчитай выручку за месяц”, не учитывая возвраты, бонусы и особенности учёта у разных подразделений. Простой Text-to-SQL агент без понимания бизнес-логики бесполезен.

Мне это чем-то напоминает известный мем про
select * from some_ideal_clean_and_pristine.table_that_you_think_exist


🔸 Другая проблема в том, что LLM падки на галлюцинации и генерацию цифр, которые не существуют в реальности.
Чтобы сделать надёжный llm-интерфейс к данным, используют четыре подхода:
1. structured output generation — сначала модель выдаёт проверяемый код (SQL, Python), а уже потом текст
2. strict rules enforcement — автоматическая валидация запросов по заранее прописанным бизнес-правилам.
3. system prompt enhancements — промпты, обогащённые метаданными (источник, период, ключевые переменные)
4. semantic layer — словари синонимов, кастомные правила и онтологии, переводящие «человеческий» запрос в точный термин БД
Про семантический слой и LLM-боты к данным 2/2

🔸 Разберем отдельно семантический слой. Он в чём-то объединяет все описанные выше техники:
— Вывод структурированных данных прежде, чем формировать текстовый ответ (SQL-запросы или код всегда проверяемы),
— Жёсткое соблюдение встроенных правил (минимальные объёмы выборки, фиксированные временные интервалы),
— Улучшенные системные промпты, обогащённые метаданными (источник, период, важные переменные),

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

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

Если интересна эта тема, подписывайтесь на канал про семантический слой от команды Synmetrix: @semanticlayer
#вести_с_полей

🌺 .airflowignore или как в нашей команде ускорили обновление дагов на порядок

🔸 В Airflow есть аналог .gitignore — конфигурационный файлик, который нужно поместить в корень DAG_FOLDER.

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

🔸 В Airflow есть отдельный компонент scheduler, одна из задач которого — парсить даги и записывать их структуру в бэкенд-базу. В итоге это всё и попадает в UI, и определяет последовательность запуска.

У нас есть сотни .py и связанных с ними файлов для дата-приложений. По этим файлам и вложенным директориям бедный шедулер пробегался в каждом цикле — и конечно же он не успевал это делать за адекватное время — цикл загрузки обновлений дага выходил далеко за 5 минут. После добавления в корень файла .airflowignore с одной строкой всё начало "летать".

.*


Под капотом используется re.findall(), т.е. у нас пропускаются все файлы, где всё равно нет ни одного дага.

Проверь, может и на твоём проекте пригодится ;)
Please open Telegram to view this post
VIEW IN TELEGRAM
🔸 Ещё один мок-собес вышел, на этот раз с Junior DE

Знаю, что прошлое видео с джуном многим зашло -- welcome. В этот раз пришёл крепкий джун, верю в успешность его карьеры :)

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

https://youtu.be/mMrjKEgBWXI
Я не смог выбрать один мем)
Data Lakehouse становится более популярным в России. И я считаю, что это хорошо

🔸 В данном посте я предлагаю воспринимать Data Lakehouse (DLH) так:
* Data Lake, обычно на S3-совместимом объектном хранилище
* в котором лежат данные в табличном формате Iceberg, Delta или Hudi
* доступ через федеративный движок, обычно Trino (ранее известный как Presto)
* dbt для управления трансформациями

То есть обвязка вокруг Data Lake позволяет исключить из цепочки DWH вроде Greenplum без потери функционала.

🔸 Какие плюсы у такого подхода:
* Меньше зоопарк - проще сопровождать и масштабировать платформу
* Меньше инструментов для изучения, по крайней мере для будущих дата инженеров
* Инструменты можно развернуть в контейнерах и иметь одинаковую по составу инфраструктуру на Dev, в CI тестах и на Prod
* Меньше интеграций -- быстрее разработка пайплайнов и доставка данных
* Унификация кода Transform: после загрузки в озеро данных все трансформации выполняются через один инструмент

🔸 А минусы какие-то есть?
* Нужно разобраться в новом подходе и адаптироваться к технологиям
* Скорость доступа к данным может быть в среднем ниже, но Trino продолжают улучшать частыми релизами
* Некоторые инструменты ещё могут быть недостаточно зрелыми для Production, часто меняться от версии к версии
* Лучшие практики ещё нарабатываются, а шишки набиваются первопроходцами

И, как с любыми проектами миграций, -- работа у дата инженеров не заканчивается :)

Пиши свои мысли -- уже удалось потрогать новые блестящие технологии?
#вести_с_полей

Про тестирование DE кода в контейнерах


🔸Я больше 6 лет в Data мире, и все эти годы я сталкиваюсь с проблемами в тестировании. DE это про интеграции многих сервисов между собой, и написать полноценный "mock" не всегда получается. В коде столько всего может пойти не так, что многие релизы выкатываются с ожиданием, что понадобятся срочные доработки.

Оказывается, что всё это время существовало и развивалось классное решение для инфраструктуры в контейнерах -- Testcontainers, ответвлении пакета pytest. Делюсь.

🔸 Если всю вашу инфраструктуру на продакшене можно описать как некую систему контейнеров, то их же (в облегчённой конфигурации) можно использовать в CI тестах и на dev среде. Вот что это даёт:
. Автоматические тесты при каждом Pull/Merge request
. Унифицированный подход для python/sql/whatever-based сервисов
. Сервисы не нужно "mock'ать", пытаясь воспроизвести их поведение -- просто подними сервис и работай с ним
. Можно подготовить обезличенные данные по каждому источнику и снэпшоты, а потом прогонять интеграционные end2end тесты и сверять результат
. Зависимости описываются через параметры @pytest.fixture
. Можно управлять областью применения и временем жизни контейнера -- держать один на все тесты или запускать свой для каждого кейса
. Сеть описывается парой строчек, встроенный service-discovery через alias'ы

🔸 Пример есть на сайте с документацией пакета. Также можно подставить любой контейнер, не только postgres, но для нашего проекта хватает встроенных:
from testcontainers.core.network import Network
from testcontainers.minio import MinioContainer
from testcontainers.postgres import PostgresContainer
from testcontainers.trino import TrinoContainer
#реклама

Стратегия: что мы делаем и что мы не делаем
1/2

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

🔸 О курсе и преподавателе
Основную мысль первых четырёх уроков сформулирую так:
"Стратегия: что мы делаем и что мы не делаем 
для того чтобы занять или сохранить конкурентную позицию".

Лекции ведёт один из сооснователей школы, Вячеслав Панкратов, и ведёт их увлекательно.

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

С технической стороны курс однозначно рекомендую.

🔸 Инсайты
. история страны влияет на культуру, а это влияет на подход к ведению бизнеса (американцы захватывали континент с преимуществом в силе и ещё "не навоевались", японцы закреплялись на маленьком острове и делили территорию между кланами многие сотни лет)
. выбирая компанию для построения карьеры, посмотри на среднее "время жизни" сотрудников
. если хочешь захватывать международный рынок – учти особенности того, как они “там” уже выжили, а мы “только собираемся”
. стартап-акселератор это в первую очередь БИЗНЕС, который делает spray and pray и жертвует временем и силами 9/10 команд
. стратегия это всегда выбор и ответственность за последствия, даже если это “а по ходу разберёмся” или “закроем глаза и шагнём вперёд”
. планы на любую битву разрабатываются в мирное время -- когда есть проблема, уже нужно действовать, а не планировать
. выгоды не там, где ты переконцентрирован
Стратегия: что мы делаем и что мы не делаем 2/2

🔸 Что я понял о себе
Я начал замечать свою привычную модель поведения — "поддерживать статус-кво" и следить чтобы всегда были ресурсы в моменте "сейчас". От размышлений о возможностях роста убегаю в оптимизацию операционки на проекте и сменяющиеся хобби. Из-за этого у меня всегда находится разумное объяснение для откладывания "несрочного и важного". Даже когда освобождаю время от рутины для трансформации деятельности — как с переходом от разовых консультаций по DE к менторству "до оффера" — я очень долго решаюсь на такой шаг. Приходится подталкивать себя со всех сторон.

Получается, что моя текущая стратегия в плане личного и карьерного развития звучит так: "нагрузить себя мелкими задачами, чтобы некогда было думать о будущем". Это, конечно, помогает становиться лучше в своём ремесле и повышать насмотренность как Data Engineer. Но если описать последний год такими словами и всмотреться в формулировку, сказать себе спасибо за выбранный путь я не могу.

🔸 Что дальше
Хорошо то, что если честно взглянуть себе в глаза, можно осознанно поменять вектор. Я на момент написания этого поста ещё не собрался резко менять жизнь, но чувствую, что готовлюсь к этому. Знания и мысли из курса помогают как запустить размышления, так и направить их в практическое русло через конкретные инструменты.

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

По крайней мере, я начал замедляться и думать.

Курс можно купить по ссылке: https://stratoplan-school.com/strategy/dataeng
#вести_с_полей

Как ускорить загрузку из X в Greenplum (или Postgres
) (даже) через JDBC коннектор

🔸 Многие слышали, что вставлять в OLAP СУБД лучше большими батчами, хотя бы по 5-10 тысяч строк. И для этого как раз существует параметр batchsize, верно?

Оказывается, даже если приложение (python/spark/X) упаковывает insert'ы вместе, база может разбирать их на отдельные инсёрты и вставлять примерно вот так:
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL: parameters: $1 = 'Post no. 1', $2 = '1'
LOG: execute S_2: insert into post (title, id) values ($1, $2)
DETAIL: parameters: $1 = 'Post no. 2', $2 = '2'
LOG: execute S_2: insert into post (title, id) values ($1, $2)
DETAIL: parameters: $1 = 'Post no. 3', $2 = '3'
LOG: execute S_2: insert into post (title, id) values ($1, $2)
DETAIL: parameters: $1 = 'Post no. 4', $2 = '4'
LOG: execute S_2: insert into post (title, id) values ($1, $2)
DETAIL: parameters: $1 = 'Post no. 5', $2 = '5'


🔸 Но если добавить в connection string параметр ?reWriteBatchedInserts=true, получим ожидаемый результат:
LOG:  execute s_3: insert into post (title, id) values ($1, $2),($3, $4),($5, $6),($7, $8)
DETAIL: parameters: $1 = 'Post no. 1', $2 = '1', $3 = 'Post no. 2', $4 = '2', $5 = 'Post no. 3', $6 = '3', $7 = 'Post no. 4', $8 = '4'
LOG: execute s_3: insert into post (title, id) values ($1, $2)
DETAIL: parameters: $1 = 'Post no. 5', $2 = '5'


Именно в размере batchsize упаковка инсёртов почему-то не гарантируется (в примере = 5), СУБД может разбивать на несколько запросов. Но всё равно это сильно разгрузит базу.

p.s. Настройка появилась как раз в PostgreSQL 9.4, на котором основан Greenplum 6. Совпадение?)

p.p.s. Если у системы загрузки есть специальный коннектор для Greenplum и источник тоже распределённый, обязательно используй коннектор. Он будет связывать ноды напрямую, в обход мастера
2025/07/07 22:28:30
Back to Top
HTML Embed Code: