Инженер и данные
721 subscribers
39 photos
30 links
Канал про инженерный подход к работе с данными


Автор: Андрей Демидов - lead data engineer.
Связаться: @andrewdemidovv
Download Telegram
Теория разбитых окон

"Теория разбитых окон" появилась в США в начале 1980-х годов.
Суть теории в том, что признаки беспорядка (разбитое окно, граффити, мусор) сигнализируют: за этим местом не следят.
Наблюдали такую картину: рядом могут стоять два здания — одно ухоженное, другое с разбитым окном. И именно второе продолжали портить снова и снова. Если разбито одно окно, то вскоре разобьют и другое, а потом и третье и здание быстро приходит в упадок.

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


По-моему, теория работает много где, в том числе и в инжиниринге данных.

У меня есть пунктик по поводу порядка в нейминге (таблиц, свойств, типов), в синтаксисе, в структуре директорий в репозитории и тд. Это как порядок дома или в городе: разбитое окно нужно менять сразу.

Вот пример.
Мы пишем события. У события есть свойство type. Обычно его пишем в snake_case: something_occured. Но однажды кто-то пишет someThing_occured. Мне такие вещи режут глаз. Смешение camelCase и snake_case в одном значении - перебор. Мы это сразу поправили. А оставили бы так и завтра пришел бы другой, посмотрел и написал в новом событии Smth Occured. Потом третий добавил бы "smth occured_new Final 2025". Окна начали бы разбивать.

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

©️Окна будут разбивать. Может парочку разобьете даже вы сами. 🫣 Главное — заметить это и быстро навести порядок!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤4
Покажи деньги!

В последнее время я много размышляю о конечной пользе для бизнеса от существования данных и существования дата-платформы. Поэтому мне понравился недавний пост Джо Рейса — автора книги Fundamentals of Data Engineering.
Вот небольшая выдержка из него:

Как продать моделирование данных?

Анти-патерн: Продажа «качества данных» или «единого источника правды» в качестве конечной цели.

«Нам нужно моделировать данные, чтобы улучшить качество данных» — звучит прекрасно. Проблема в том, что «качество данных» — абстрактное понятие, о котором даже опытные специалисты по данным не всегда могут договориться. А «единственный источник истины» звучит отлично в теории, но что это на самом деле означает и достижимо ли это? Оба выражения — всего лишь технические средства для достижения цели.
Когда бизнес-лидер слышит такие фразы, он скорее всего думает: «И что дальше?» Плохое качество данных — не его проблема. Его проблема — последствия плохого качества данных.


Именно эта часть прям "попала в меня" и заставила задуматься. Я много раз заявлял бизнесу, что качество — цель! 🫣
Но качество не цель, а средство.

PS. Увидел ещё на днях выражение: data-to-dollar, в котором заключена суть ожиданий бизнеса. 💸 коротко и ёмко! 👍
❤7👍4
Ловушка кодера

Писать код или использовать готовый инструмент? 🤔

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

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

Это я назвал ловушкой кодера. 👇⏭

📎 В отдельно взятой ситуации решение принимается правильное — «взять известное», но в долгосрочной перспективе понятно, что никогда не будет задачи с достаточным временем, чтобы изучить новое. То есть снова и снова будет приниматься "правильное" решение....

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

Если инструмент нужен прямо сейчас, то уже поздно разбиратся, лучше кодить. Но только инструмент надо тоже изучить в спокойном режиме. Это инвестиция в будущее – выход из ловушки.🙌

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

©️Инструменты и технологии позволяют решать задачи быстро только тогда, когда ты знаешь, как ими пользоваться прямо сейчас. В краткосрочной перспективе лучше взять известное, а в долгосрочной — изучить разное и выбрать лучшее.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7🤔2❤1💩1
Материализация vs стриминг в ETL: контроль потребления памяти в Airflow

Рассмотрим простой ETL-процесс, реализованный в Airflow.

Есть источник и назначение. На практике это может быть база приложения → DWH или DWH → какая-то система (reverse ETL). Посередине есть оркестратор, который отправляет запрос в источник, получает результат и отправляет его в назначение.
Если вы используете встроенные операторы Airflow, то это будут две разные задачи: extract и insert. Задачи выполняются последовательно, и результат первой часто полностью материализуется в памяти воркера. Вот тут и кроется крайне невыгодное использование ресурсов: если у вас много DAG'ов или объём данных достаточно большой, Airflow начинает активно потреблять память воркеров.
В итоге вы либо
🔸платите больше за ресурсы,
🔸играете с расписанием, чтобы в один момент времени было меньше данных в памяти и воркер не падал,
🔸режете объём данных.
Все варианты плохие хотя бы потому, что ресурсы воркера вообще начинают участвовать в уравнении. Зависимость от памяти становится ограничивающим фактором.

Эту проблему можно решить, если сделать так, чтобы оркестратор оставался оркестратором, а не буфером между источником и назначением.
Суть решения — организовать процесс как микробатч-стриминг. Тогда в памяти воркера в любой момент времени будет только один микробатч (например, 1000 строк).
Достичь этого можно с помощью специального Python-объекта — Generator.
Для тех, кто хорошо разбирается в программировании, я нового ничего не открою.

Такой подход даёт две серьёзные возможности:
1️⃣Можно делать трансфер практически любого объёма без роста потребления памяти воркера.
2️⃣Можно запускать больше процессов трансфера параллельно, потому что они почти не конкурируют за память (память ограничена размером микробатча).

Дальше — техническая часть.

Многие встроенные операторы и хуки в Airflow по умолчанию материализуют результат запроса в памяти воркера. Поэтому потребуется написать немного кода.

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

Итак, что нам нужно.
Во-первых, убрать разрыв на две задачи (извлечение/вставка) и обеспечить одну — трансфер. Это позволит контролировать использование памяти внутри одного процесса на одном воркере.
Во-вторых, нужен адаптер для источника. Его задача — получить запрос и вернуть не данные, а специальный Python-объект — Generator.
Generator не содержит сами данные. Он лишь определяет, как их получать. При итерации он каждый раз возвращает очередную порцию данных.
Большинство баз поддерживают серверные курсоры или потоковую выдачу результатов. Адаптер делает запрос к источнику, но не забирает всё сразу — он получает данные частями.
Например, SQLAlchemy умеет работать в streaming-режиме через соответствующие параметры соединения.
Далее этот Generator передаётся адаптеру назначения. Он итерируется по нему и за раз обрабатывает только небольшой батч данных, освобождая память после каждой обработки.
В любой момент времени в памяти воркера находится только микробатч. 🙌

Для непрограммиста это может выглядеть необычно: фактическое извлечение данных происходит в момент вставки, а до этого между функциями передаётся лишь абстрактный объект, который сам по себе почти ничего не весит.🤯

Примерно год назад мы реализовали такой подход у себя.🧐

С тех пор ошибки DAG'ов из-за нехватки памяти на воркерах перестали быть проблемой.
Сейчас у нас есть универсальный оператор и набор адаптеров для баз и сервисов, реализующих потоковое поведение. Адаптеры инкапсулируют логику стриминга за простыми интерфейсами extract/insert, поэтому оркестратор остаётся только управляющим слоем.

Это уже архитектурный подход — разделение orchestration и data transfer.

Для старта не обязательно строить такую обвязку. Того же поведения можно добиться и обычной функцией внутри одного таска.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥7❤2
Попробовал code agent

На неделе впервые попробовал code agent. Пока что не multi agent со множеством ролей (к этому ещё приду), а просто один агент, который выполняет задачу полностью, даже вместе с деплоем.

Я, конечно, много видел упоминаний и описаний того, как оно работает, но пока сам не попробуешь на своей реальной задаче, всё равно непонятно. Тут как раз появилась простая задачка – идеальная, чтобы начать работать с агентом. И результат превзошёл мои ожидания!

Мне нужно было сделать простой прокси-микросервис, который состоит из AWS API Gateway и одной AWS Lambda. Всё, что делает сервис, — это принимает POST-запрос, проверяет аутентификацию и передаёт его дальше на внутренний API endpoint. Мне нужно было, чтобы агент написал terraform, саму лямбду, тесты. Про то, что он может и задеплоить, я даже и не думал, когда начал.

В пустом репозитории я создал readme файл, описал там задачу сервиса примерно так же, как описал выше. Открыл чат с агентом и попросил его создать сервис. И он реально начал создавать файлы! Не примеры кода, а зависимые друг от друга файлы, которые вместе представляют собой работающий сервис. Я, в общем-то, так и хотел, но увидеть на практике - другое дело. Он уже был не чатом, не ассистентом, а разработчиком.

Затем мне было интересно увидеть, как он будет взаимодействовать со внешними элементами. Я просил его:
▫️задеплоить сервис (stage).
▫️сделать git операции: commit и push в удаленный репозиторий.
▫️провести интеграционный тест: запустить код лямбды локально, отправить реальный запрос на реальный endpoint и оценить результат.

Он выполнял команды terraform, aws cli, git, запускал .py файлы, получал ответы, адаптировался, пробовал снова и... успешно справлялся.

‼️Среди всей этой магии был один важный момент. Он совершил глупую, но серьезную ошибку: в одной из итераций он удалил проверку токена авторизации, оставив только проверку наличия заголовка. Ошибка опасная. Я заметил это, просматривая код наискосок (я не читал каждую строку), попросил его поправить, и он конечно признал ошибку и поправил. Да, наверное можно в конце попросить его же самого сделать ревью и, возможно, он такое заметит сам (в тот момент я не подумал это попробовать).
Главное – остаётся риск ошибки, если "оставить его одного". При этом не стоит проваливаться слишком глубоко в ревью и переписывать всё доводя до идеала. Без перфекционизма. Иначе вместо помощника, который даёт результат, вы сами себе создадите лишнюю работу.


©️В итоге я остался под впечатлением.
(Даже жене вечером рассказал, хоть она и не поняла половину терминов😁).

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

Я точно буду использовать его больше. Следующий интересный шаг – пробовать подключать его напрямую к базе данных.

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

Кстати, я использовал бесплатный vs code и gpt codex, включённый в gpt plus подписку.
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍4❤2😁1
Нужно ли хранить историю на уровне моделей?

Часто это воспринимается как дефолт:
делаем модель → сразу закладываем версионирование, SCD, valid_from / valid_to.

Но вопрос — действительно ли это всегда нужно?
История, конечно, важна.
Но важно разделить уровни.

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

🤔 На уровне model layer всё менее однозначно.
Изменения там обычно происходят по двум причинам:
🔹меняются данные в источнике
🔹меняется логика трансформации

Но хранить историю на model layer уровне имеет смысл только тогда, когда у этого есть бизнес-ценность, то есть когда история является частью публичной модели данных. Например, история состояния заказа.

Во всех остальных случаях это скорее техническая страховка.

Частый аргумент — observability:
нужно иметь возможность разобраться, почему раньше считалось иначе.
Но для этого не обязательно хранить историю в моделях. Observability можно обеспечить имея:
🔵полная история на ingestion layer
🔵воспроизводимые (детерминированные) трансформации

Что значит детерминированность?
В общем смысле это "один и тот же input всегда ведёт к одному и тому же output". В случае sql трансформаций input это и сам запрос и данные, к которым он обращается.
Если:
🔹 данные на ingestion layer неизменяемы и имеют временную ось (meta timeline)
🔹 функции/запросы имеют свою историю изменений (хотя бы git)

то в любой момент времени можно восстановить нужный input и получить тот же самый output.

Это и есть детерминированный пайплайн.

Тогда:

история в ingestion layer + воспроизводимая логика = возможность восстановить результат на любой момент 🙌


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

И тогда вопрос сводится к простому:

история в model layer — это осознанное бизнес-требование
или компенсация недостаточной воспроизводимости пайплайна?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
Искажение модели

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

Организационная структура — один из частых источников искажения модели данных.

❗️Элементы оргструктуры начинают определять сущности, метрики, сегментации.

❗️Бизнес-определения начинают разъезжаться —
не потому что меняется бизнес,
а потому что разные отделы «так видят».

❗️Границы ответственности превращаются в границы данных.

И со временем это начинает выглядеть как естественная часть модели.

Например.

Одна команда назовёт запросы клиентов case, другая — lead.
Какая разница с точки зрения бизнеса, если и то и другое — запрос клиента?

Это искажение.

Или маркетинг разделён на направления:
реклама, партнёры, органика, email.

Это нормальное управленческое решение —
разделить ответственность и сфокусировать команды.

Но дальше каждое направление начинает выстраивать свою картину:
свои метрики, свои воронки, свои правила атрибуции.

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

Хотя это один поток:
трафик → клиенты → выручка.

Границы, введённые для удобства управления,
начинают восприниматься как ограничения самой модели.

Искажение.

Со временем это закрепляется в данных, отчётах и процессах.
И начинает влиять на решения.

Что с этим делать

При моделировании важно абстрагироваться от команд, отделов и ролей.
Полезные вопросы:
🔵Эта сущность будет существовать, если завтра отдел расформируют?
🔵 Как изменится сегментация, если завтра два отдела объединят в один?

Организационная структура тоже может быть частью данных — но явно.
Она не должна тихо влиять на определения бизнес-сущностей.

©️В корректной модели оргструктура — это отдельный слой, который дополняет бизнес-объекты, а не подменяет их.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4❤‍🔥1🔥1💯1
Полезный ресурс про то, что происходит в мире ai. Не только про код, а вообще. Вот ссылка на сайт, но у них ещё есть newsletter. Не реклама. У ребят 700 тысяч подписчиков и им реклама у меня точно не нужна 😂

Я читаю у них далеко не все, но чтобы оставаться в теме, по-моему, посматривать стоит.

Например, в последнем посте есть ссылка на репозиторий со скилами. Выглядит интересно 👍 я вот еще в использование скилов не погружался. Завтра попробую.
🔥4
Нужно запретить сортировку в дата-инжиниринге на законодательном уровне.

* так пошутил инженер из Databricks, объясняя работу Spark. Он показал, что сортировка увеличивает потребление ресурсов и время выполнения задачи в несколько раз. Мне понравилась эта цитата, потому что я пришел ровно к тому же выводу работая с Clickhouse. В итоге пришлось изменить свои привычки, наработанные в строковых базах.

©️Большая часть сортировок в запросах существует не потому, что она нужна задаче. Она существует потому, что мы привыкли писать SQL определённым образом. Проблема справедлива для разных систем, но особенно хорошо видна на примере Clickhouse.

▫️Привычка первая — одна строка на ключ.
Если вы много работали с PostgreSQL, рука сама тянется к distinct on или похожим конструкциям. И там это работает хорошо. ClickHouse тоже поддерживает и distinct on и limit 1 by, но они требуют сортировку. Забавно, что AI-ассистенты тоже любят такие конструкции и регулярно предлагают их как решение по умолчанию.
Я тоже использовал такие конструкции, пока не начал регулярно сталкиваться с ростом потребления памяти и периодическими падениями запросов.
В итоге везде заменил их на GROUP BY с агрегатными функциями вроде argMax() и argMin(). Агрегация - вообще любимая операция Clickhouse.

▫️Привычка вторая — посмотреть последние данные через
select * from table order by timestamp (да, некоторые даже не пишут limit полагаясь на IDE, которая получит ограниченное количество строк).
На практике человеку обычно нужно не 100 самых последних строк во всей таблице, а просто посмотреть свежие данные. То есть точная сортировка не является частью задачи, а скорее привычкой. Фильтр по последнему часу плюс limit решают это за доли секунды без сортировки вообще. Пока писал этот пост, прогнал пару запросов на одной из наших таблиц в Clickhouse на 300М записей:
✔️фильтр + лимит - 800 мс
❌сортировка + лимит - 9 минут!

Теперь я стал смотреть критически на сортировку везде. И нашёл order by в пайплайнах, где он просто стоит как артефакт после чьей-то работы. Никто не убрал, а база честно сортирует данные при каждом запуске. И если для строковой базы это терпимо, то для колончатой или для распределенных вычислений (типа Spark) - это выстрел в ногу.

©️Перед тем как написать ORDER BY — убедитесь, что не нарушаете закон. ☝️😁
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤2🔥2
Когда в последний день перед отпуском пытаешься доделать всё😁
😁12❤1
Асимметрия обратной связи

На днях поймал себя на мысли.

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

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

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

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

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

А когда результат твоей работы — данные, всё становится иначе.

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

Но мы почти никогда не видим результат этой цепочки.

Мы не знаем,
– сколько вопросов сегодня было решено благодаря данным.
– сколько бизнес-проблем удалось обнаружить.
– сколько решений приняли руководители.
– сколько возможностей для бизнеса нашли.

Зато есть другая сторона.

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

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

Но почти никто не приходит сказать:

«Сегодня снова работал с отчетами. Получил ответы на все вопросы. Всё было как нужно.»

Получается интересная особенность профессии.

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

Возможно, именно асимметрия обратной связи и создает психологическую нагрузку.
💯4👍3🤔3😁1🤝1
Языки программирования были нужны только человеку?

Мне пришла одна мысль и я попытался ее развить и порассуждать.

Что, если стек абстракций — от языков программирования до фреймворков — появился прежде всего как интерфейс для человека? Тогда что произойдёт с ним, если новым пользователем вычислительной техники становится AI?

Если оглянуться назад, развитие информационных технологий почти всегда шло через добавление слоёв абстракции:
железо → операционные системы → низкоуровневые языки → высокоуровневые языки → фреймворки → no code / serverless

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

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

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

По сути, языки программирования — это интерфейс. Не для машины, а для человека. А теперь появляется новый «пользователь» — AI. И у него нет наших ограничений: ему несложно держать в голове детали, он не устаёт от низкоуровневой работы, ему не нужно упрощать задачу. Значит, абстракции, созданные для человека, ему не нужны?

Можно представить сценарий, где AI постепенно снимает уровни. Сначала работает через привычные нам языки, потом опускается ниже — туда, где меньше ограничений и больше контроля. Он может работать с промежуточными представлениями, машинным кодом или другими внутренними формами.

Например, подумаем о компилируемых языках. Они же для человека: человек пишет код, а компилятор переводит его из формата, удобного человеку, в формат, удобный машине. Если человека в процессе нет, всё может быть наоборот. AI может работать с представлением, удобным машине, а если человеку понадобится посмотреть на результат — «компилировать» его обратно в естественный язык. Получается своеобразная обратная компиляция: не человек пишет код и переводит его для машины, а машина формирует решение в удобном для себя представлении и при необходимости переводит его обратно для человека

Другой пример. Meta выпустила LLM Compiler — модель, обученную на LLVM IR и ассемблерном коде для задач оптимизации. LLVM IR — это промежуточное представление кода, расположенное ниже привычных высокоуровневых языков программирования.
То есть инженеры в этом случае уже пришли к тому, что "наши" языки программирования только помешают AI.


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

Однако, есть и другой слой, который пока что все таки нужен.
До сих пор речь шла об абстракциях, которые помогают человеку взаимодействовать с вычислительной системой.
Но существует и другой класс абстракций. При взаимодействии независимых систем всё равно нужны договорённости — общие протоколы, стандарты и форматы обмена. Здесь проходит фундаментальное различие между двумя типами абстракций:
1) появились как компенсация человеческих ограничений. Они помогают человеку справляться со сложностью вычислительных систем.
2) появились как механизм взаимодействия между независимыми системами. Они помогают системам договариваться друг с другом.

Первые могут оказаться временными. Вторые, вероятно, останутся с нами гораздо дольше.

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

Мы привыкли воспринимать стек абстракций как естественную эволюцию вычислительной техники. Каждый новый слой казался шагом вперёд по сравнению с предыдущим. Возможно, это была не столько эволюция компьютеров, сколько эволюция интерфейсов для человека.
❤8💯2
Software ручной работы

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

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

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

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

Хотя у этой же аналогии есть интересное следствие. Кузнецы ведь не исчезли. Они просто перестали быть массовым способом производства. Возможно, останутся и разработчики эксклюзивного software ручной работы.
👍5
Модель космического масштаба

Select count(*)
From solar_system.planets
-- 2005: 9
-- 2006: 8

История о том, как строгая работа с семантической моделью исключила Плутон из списка планет.
В 2005 был открыт объект Эрида сопоставимый с Плутоном по размеру и массе. Тогда стало понятно, что считать Плутон планетой, а Эриду нет - разрушение консистентности модели. Неточное определение того, что такое планета, оставляет пространство для интерпретации, а значит, для ошибки и искажения.

Возникла неопределённость, которую решили на уровне семантической модели — изменили определение планеты, приняли единое формальное определение. Однако Плутон перестал соответствовать определению и перестал быть планетой. Официальное решение IAU 2006 года: Definition of a Planet⁠

Решение серьёзное и влекущее за собой множество последствий. Вдруг множество книг, научных статей, учебников и тд стали устаревшими. Презентации, отчёты, дашборды стали показывать количество планет не 9, а 8. Никто на научных конференциях больше не говорит, что планет 9, объясняя это тем, что "мы так привыкли" и что "всегда считали так" и что "метрики поедут". Никто не пишет в научной статье, что планет 9, потому что "руководитель отдела продаж планет просил оставить 9".

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

Изменение определения коснулось множества downstream процессов, но это не аргумент против уточнения модели.

По-моему, эта история - хороший пример управления семантической моделью на доменном уровне.
❤3🔥2
Инкрементальное обновление данных в dbt + ClickHouse

Я некоторое время экспериментировал с разными способами обновления моделей в связке dbt + ClickHouse.

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

Full refresh остаётся самым простым и надёжным вариантом — пока пересчитывать весь dataset не становится слишком дорого. Дальше появляется довольно много вариантов, каждый со своими компромиссами.

Собрал их в небольшой cheat sheet:

— какие стратегии доступны;
— где появляется duplicate или missing-data window;
— что происходит с late enrichment и corrections;
— как отличаются dbt runtime и ClickHouse-native orchestration.

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

Подробности экспериментов и выводы разберу отдельно.
❤9👍3