Warning: Undefined array key 0 in /var/www/tgoop/function.php on line 65

Warning: Trying to access array offset on value of type null in /var/www/tgoop/function.php on line 65
152 - Telegram Web
Telegram Web
Денормализация данных: когда и зачем нарушать правила

Денормализация — это намеренное введение избыточности данных в таблице. Звучит как ересь, не так ли? Мы же так долго их номрализовывали! Однако, в мире больших данных и высоких нагрузок этот подход имеет место быть.

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

Когда применять денормализацию?
🔵Есть часто выполняемые сложные запросы с множеством соединений — денормализация может значительно ускорить их выполнение за счёт хранения предварительно агрегированных данных в одной таблице.
🔵Для систем бизнес-аналитики (BI) и хранилищ данных денормализация — обычная практика. Она позволяет быстрее выполнять сложные расчеты и агрегации.
🔵В распределенных базах данных JOIN-ы между таблицами, хранящимися на разных узлах, могут быть очень дорогостоящими. Денормализация помогает избежать этих сложных операций.

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

orders:
| order_id | customer_id | order_date |
|----------|-------------|------------|
| 1 | 101 | 2024-09-01 |

customers:
| customer_id | name | email |
|-------------|-------|----------------|
| 101 | Алиса | alice@email.ru |

order_items:
| order_id | product_id | quantity |
|----------|------------|----------|
| 1 | 201 | 2 |

products:
| product_id | name | price |
|------------|----------|-------|
| 201 | Ноутбук | 50000 |


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

SELECT
o.order_id,
c.name AS customer_name,
c.email AS customer_email,
p.name AS product_name,
oi.quantity,
p.price,
oi.quantity * p.price AS total_price,
o.order_date
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE c.name = 'Алиса';


При высокой нагрузке это может стать узким местом. В денормализованной версии мы можем хранить все нужные нам столбцы и расчёты (н-р, order_id, customer_name, customer_email, product_name, quantity, price, total_price, order_date). Когда вся информация доступна в одной таблице, это значительно ускоряет запросы на чтение:


SELECT
order_id,
customer_name,
customer_email,
product_name,
quantity,
price,
total_price,
order_date
FROM orders o
WHERE customer_name = 'Алиса';


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

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

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

А вы сталкивались с необходимостью денормализации в своих проектах? Какие подходы использовали для поддержания согласованности данных?

#dwh
Please open Telegram to view this post
VIEW IN TELEGRAM
3
QUALIFY: фильтруем результаты оконных функций

QUALIFY — SQL-конструкция, которая позволяет отфильтровать результаты после применения оконных функций 😍

Она работает аналогично WHERE, но с той разницей, что QUALIFY применяется после оконных функций, а WHERE — до них.

Напомню порядок выполнения запроса:
1. From
2. Where
3. Group by
4. Having
5. Window
6. QUALIFY
7. Distinct
8. Order by
9. Limit

Представим, что у нас есть таблица продаж, и мы хотим выбрать топ-5 продаж по каждой категории товаров. С помощью QUALIFY это можно сделать просто и эффективно:

SELECT
category,
product,
sales_amount,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales_amount DESC) AS rn
FROM sales
QUALIFY rn <= 5;

В этом запросе сначала нумеруем продажи в каждой категории по убыванию суммы продаж с помощью ROW_NUMBER(). Затем с помощью QUALIFY оставляем только первые пять записей в каждой категории. Легко и понятно.

Почему нельзя использовать WHERE вместо QUALIFY? Потому что WHERE фильтрует данные до выполнения оконных функций, а нам нужно отфильтровать данные после. Если попробовать использовать WHERE rn <= 5, SQL не поймёт, что такое rn, потому что на этапе выполнения WHERE эта колонка ещё не создана.

Конечно, можно использовать QUALIFY и с другими оконными функциями, например, RANK():

SELECT
employee_id,
department,
salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC)
AS salary_rank
FROM employees
QUALIFY salary_rank = 1;

Этот запрос выберет сотрудников с наивысшей зарплатой в каждом отделе.

Стоит отметить, что QUALIFY поддерживается не во всех СУБД. Например, в Snowflake и Teradata эта функция есть, а в PostgreSQL или MySQL её нет. В таких случаях приходится использовать подзапросы или CTE (Common Table Expressions).

Например так:

WITH ranked_sales AS (
SELECT
category,
product,
sales_amount,
RANK() OVER (PARTITION BY category ORDER BY sales_amount DESC) AS rn
FROM sales
)
SELECT *
FROM ranked_sales
WHERE rn <= 5;

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

#sql
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥4
На прошлой неделе я выступала на конференции UIC Dev с докладом "Автоматизируй это: как мы построили DWH для международного холдинга командой из 6 человек". Это был мой первый опыт участия в качестве спикера и, кажется, я справилась неплохо. Хочется зафиксировать для себя этот момент.

Мои инсайты:
🟠быть спикером и просто участником конференции — две параллельные реальности с совершенно разными мироощущениям в процессе (даже когда слушаешь чужие доклады), круто быть внутри тусовки 😍
🟠рассказывать о том, что любишь не страшно;
🟠твои слушатели — такие же люди, как и ты. Нормально чего-то не знать или быть неуверенным, хуже — ничего не делать;
🟠хорошая шутка в нужный момент — половина успеха;
🟠вторая половина — умение адаптировать свой рассказ под аудиторию и быть гибким (наше выступление было сильно лучше, чем все прогоны до этого).

Несмотря на то, что конференция была "всё обо всём" и в какой-то момент мы стали волноваться, что тема DWH не вызовет большого интересна, нас приняли отлично и вопросы задавали хорошие и к месту. Это ценно! Спасибо 🙂

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

Спасибо UIC Dev. Отличный опыт, было интересно 🐱

#life
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥54
Загрузка данных в хранилище: полная, инкрементальная и частичная перезагрузка

Что самое главное в DWH? Конечно же, данные, которые как-то должны попасть в хранилище. Чаще мы используем современные методы загрузки, но на ранних этапах или из-за тех. ограничений, или при исследованиях, мы всё также прибегаем к классическим методам.

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

При полной загрузке мы каждый раз заново забираем все данные из источника, полностью заменяя существующие данные в хранилище. Почему "полностью" курсивом? Иногда нам нужно отслеживать удалённые строки, тогда мы не просто транкейтим, а размечаем отсутствующие строки флагом DELETED.

Полная загрузка — самый простой метод со своими особенностями:
простота реализации
100% актуальность данных
высокая нагрузка при больших объемах данных
время выполнения
неэффективное использование ресурсов при небольших изменениях.

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


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

Для больших таблиц с частыми апдейтами — то, что надо. Важно❗️если нужно отслеживать изменения, у таблиц должно быть поле, содержащее дату и время обновления строки. Убедитесь, что вы можете доверять ему. Комментарии к полям могут врать! В моей практике были случаи, когда дата содержала инфу об изменении только нескольких полей из таблицы, что не было нигде явно указано 🥲 (да, иногда нужно покапаться в коде источника)

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

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


Частичная перезагрузка — гибрид предыдущих способов. Здесь мы перезагружаем только часть данных, обычно за какой-то конкретный период.
баланс актуальности и эффективности
обновление за определенный период без полной перезагрузки
удобно для данных с "окном актуальности"
сложно определить оптимальный период
риск дублей при неправильной реализации
нужна дополнительная логика для определения границ загрузки

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


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

Благодаря тому, что источники не идеальны, работа системного аналитика всегда где-то на грани творчества и здравого смысла 😇

#dwh
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3
Всегда хочется быть сильной, ведь кажется, что сила и развитие — это обязательные условия нашего времени. Но не всегда это можется, а скорее всего и не нужно. Иногда полезно отпустить стремление быть успешной, позволив себе принять слабость как временную передышку.

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

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

Будьте здоровы 🍀

#life
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍1🕊1
NULL + 50: почему иногда арифметика работает не так, как ожидается

Продолжая серию статей про #null, не могу обойти стороной арифметику.

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

| product_id | current_stock | expected_delivery |
|------------|---------------|-------------------|
| 1 | 100 | 20 |
| 2 | 50 | NULL |
| 3 | 200 | 30 |


Выполняем запрос:

SELECT
product_id,
current_stock + expected_delivery AS total_stock
FROM inventory;


Результат выполнения будет таким:

| product_id | total_stock |
|------------|-------------|
| 1 | 120 |
| 2 | NULL |
| 3 | 230 |


Почему для второго продукта итог оказался NULL вместо 50? 🤔 Ведь логично ожидать, что результат будет равен текущим запасам.

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

Что делать?
Как и всегда, важно всегда обрабатывать NULL-значения. Тут нам снова помогут функции COALESCE и IFNULL:


SELECT
product_id,
current_stock + COALESCE(expected_delivery, 0) AS total_stock
FROM inventory;


Функция COALESCE проверяет, является ли значение expected_delivery NULL, и если это так, подставляет 0. Так мы избегаем возможной ошибки, которой точно не место в наших в отчётах.

#null
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Организация мониторинга и алертинга в DWH-системах

Мониторинг и алертинг — это не просто какие-то модные слова из мира IT. Это основа, на которой держится работа с данными. Давайте разберемся, как это устроено в современных хранилищах.

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

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

Простой пример: у вас есть ежедневный процесс обновления данных об отгрузках со склада, и обычно он выполняется за 15 минут. Если мониторинг фиксирует, что процесс вдруг начал занимать час, он оповещает, что что-то пошло не так. Возможно, сломалась загрузка из источника или увеличился объем данных (тоже не плохо обратить на это внимание).

Еще одна задача — контроль качества данных. Иногда сами данные могут приходить с ошибками. Представьте, что ваш ETL процесс получил пустые строки об отгрузках вместо обычного объема данных. Хорошо настроенный мониторинг заметит это и оповестит команду.

Что конкретно стоит мониторить?
1. Процессы загрузки данных: время выполнения, наличие ошибок, объемы данных.
2. Качество данных: проверки на пустые значения, аномалии, отклонения от ожидаемых значений.
3. Работа сервера: утилизация CPU, память, доступное место на диске. Особенно важно в облачных решениях, где рост нагрузки приводит к дополнительным затратам.


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

Ещё один пример: если ETL процесс падает три раза подряд — это явно повод для тревоги. Алертинг должен отправить сообщение дежурным инженерам по оперативным каналам (но не засыпать этот канал оповещениями нон-стоп). Для этого удобно использовать мессенджеры вроде Slack, хуже — email уведомления.

Инструменты для мониторинга и алертинга
🟠 Prometheus + Grafana: отличный вариант для отслеживания метрик и визуализации данных. Prometheus собирает метрики, а Grafana показывает их в удобных дашбордах.
🟠 dbt Cloud: инструмент для разработки и тестирования ELT процессов, который также имеет встроенные возможности для мониторинга.
🟠 Snowflake Native Alerts: позволяет создавать алерты на основе запросов. Например, если количество записей в таблице падает ниже ожидаемого уровня, система автоматически уведомит об этом.
🟠 самописные решения 🐱

С чего начать?
Например, с базовых метрик для ETL процессов, а затем добавить проверки на качество данных. Используйте оповещения с пороговыми значениями. Например, алерт сработает, если время выполнения процесса превышает обычное более чем на 10%.

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

Используйте (или проектируйте) подходящие инструменты для мониторинга и системы оповещений, и не перегружайте свою команду лишними уведомлениями. Это сделает ваше хранилище надежным и эффективным. В конце концов, зачем нужным данные, если мы не можем положиться на их качество?

#dwh
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Сколько стоит твой SQL запрос?

Облачные хранилища — это гибкость и масштабируемость, простота и скорость работы 🤩 Но кроме этого — вечно растущие расходы. С каждым днём мы грузим всё больше данных, придумываем сложные расчёты и наши расходы растут 📈 Иногда вычислить что (и кто) тратит денежки компании особенно усердно — целое искусство.

Чтобы немного помочь с этой болью, Snowflake добавил новую системную таблицу — QUERY_ATTRIBUTION_HISTORY. Она позволяет решать целый ряд задач:
🔵cколько кредитов "съел" конкретный пользователь?
🔵во сколько обходится тот или иной пайплайн?
🔵какие запросы повторяются и сколько они стоят?

То есть она помогает обнаружить скрытые источники перерасхода. Например, простой SELECT, который запускается каждые пять минут, может стоить намного больше, чем ожидалось. Выявили проблему — сразу оптимизировали. Больше не нужно составлять сложные SQL-запросы, объединяя данные из нескольких таблиц. При этом вся информация хранится год, и доступ к ней можно получить всего за несколько строк кода.

Для вычисления самых злостных потребителей за последний месяц достаточно выполнить запрос:

SELECT user_name, SUM(credits_attributed_compute) AS credits
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_ATTRIBUTION_HISTORY
WHERE 1=1
AND start_time >= DATE_TRUNC('MONTH', CURRENT_DATE)
AND start_time < CURRENT_DATE
GROUP BY user_name
ORDER BY credits desc;


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

Что стоит помнить? Не учитываются:
🔵расходы на простои виртуальных варехаузов (про них я рассказывала в одной из статей про #snowflake)
🔵serverless-функции
🔵хранение данных

Документация по QUERY_ATTRIBUTION_HISTORY здесь.

#snowflake
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Прокачиваем SQL-запросы с фишками оконных функций

Многие аналитики активно используют базовые оконные функции, но не всегда знают, как применять такие инструменты, как фрейм окна (window frame). А ведь это сделает запросы ещё более читабельными и эффективными. Давайте разбираться вместе.

Фрейм определяет набор строк для вычислений оконной функции относительно текущей строки.


В этой статье рассмотрим два способа определить, какие строки включать в окно для расчетов: ROWS и RANGE.

Начнем с ROWS BETWEEN. Эта конструкция работает с физическими строками и помогает анализировать конкретное количество записей до и после текущей строки. Чтобы стало понятнее, рассмотрим пример: мы хотим рассчитать скользящую сумму продаж за последние 3 дня, включая текущий день. Для этого подсчёта нам необходимо от каждой строки отсчитать две строки назад и суммировать значения продаж за эти дни.


| sales_date | sales_amount |
|------------|--------------|
| 2024-01-01 | 100 |
| 2024-01-02 | 150 |
| 2024-01-03 | 200 |
| 2024-01-04 | 250 |



SELECT
sales_date,
sales_amount,
SUM(sales_amount) OVER (
ORDER BY sales_date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS rolling_sum
FROM sales_daily;


Результат:

| sales_date | sales_amount | rolling_sum |
|------------|--------------|-------------|
| 2024-01-01 | 100 | 100 |
| 2024-01-02 | 150 | 250 |
| 2024-01-03 | 200 | 450 |
| 2024-01-04 | 250 | 600 |


Выражением ROWS BETWEEN 2 PRECEDING AND CURRENT ROW мы буквально говорим, что нужно от каждой строки отсчитывать две строки назад и суммировать значения продаж за эти дни (включая значение в текущей). Таким образом, каждая строка будет содержать сумму продаж за текущий день и два предыдущих. Важно! В нашей исходной витрине данные уже сгруппированы по дням, поэтому в данном случае корректно говорить Х дней назад, но по сути мы говорим про строки.

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

Нужно рассчитать среднюю цену за последние 3 дня от каждой даты:

| price_date | stock_price |
|-------------|-------------|
| 2024-01-01 | 100 |
| 2024-01-01 | 102 |
| 2024-01-02 | 105 |
| 2024-01-04 | 103 |
| 2024-01-04 | 106 |
| 2024-01-06 | 110 |



SELECT
price_date,
stock_price,
AVG(stock_price) OVER (
ORDER BY price_date
RANGE BETWEEN INTERVAL '3' DAY PRECEDING AND CURRENT ROW
) AS avg_price_3days
FROM stock_prices;


Результат:

| price_date | stock_price | avg_price_3days |
|------------|-------------|-----------------|
| 2024-01-01 | 100 | 101.00 |
| 2024-01-01 | 102 | 101.00 |
| 2024-01-02 | 105 | 102.33 |
| 2024-01-04 | 103 | 103.20 |
| 2024-01-04 | 106 | 103.20 |
| 2024-01-06 | 110 | 106.33 |


При использовании RANGE все строки с одинаковым значением столбца, указанного в ORDER BY, обрабатываются вместе. А RANGE BETWEEN INTERVAL '3' DAY PRECEDING AND CURRENT ROW говорит о том, что нужно посчитать значения в фрейме с интервалом 3 дня до текущей строки.

Обратите внимание, что даты 2024-01-03 и 2024-01-05 отсутствуют в таблице. Когда мы используем указанный RANGE BETWEEN, SQL ищет все строки, где price_date находится в диапазоне от текущей даты минус календарных 3 дня, то есть учитывает только имеющиеся даты в этом диапазоне.

Поняли разницу? RANGE учитывает все записи в указанном временном интервале, даже если их много. А ROWS всегда отсчитывает фиксированное количество строк.

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

#sql
👍4
Обожаю Snowflake за множество классных функций, делающих sql-код более читабельным. При этом специально "переучиваться" для работы в снежке не нужно, так как он поддерживает всем знакомый (ну я надеюсь) стандарт ANSI SQL. Просто каждый раз в работе (или листая документацию) ты находишь прикольные фишки, которые хочется использовать.

Например, как бы вы посчитали, сколько задач разработчиков завершено до дедлайна, а сколько — нет? Обычно пришлось бы писать что-то вроде:

SELECT
developer,
SUM(CASE WHEN completion_date <= deadline THEN 1 ELSE 0 END) AS on_time_tasks,
SUM(CASE WHEN completion_date > deadline THEN 1 ELSE 0 END) AS late_tasks
FROM tasks
GROUP BY developer;


В Snowflake этот подсчёт выглядит куда лаконичнее:

SELECT
developer,
COUNT_IF(completion_date <= deadline) AS on_time_tasks,
COUNT_IF(completion_date > deadline) AS late_tasks
FROM tasks
GROUP BY developer;


Кажется, что это незначительная мелочь? Но насколько приятнее и понятнее становится разбирать тысячи строк какого-нибудь сложного аналитического запроса. Краткость — сила!

#snowflake #sql
👍2🔥1
Полезные привычки для продуктивности

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

Что помогает лично мне?
🟢 систематизация — в душé где-то очень глубоко я человек-система и мне важно разложить дела по полочкам, поэтому активно веду календарь, заметки и прочее. Большие вещи всегда декомпозирую на маленькие и простые ("есть слона по частям" набило оскомину, но это реально упрощает жизнь).
🟢 не нужно стараться успеть всё, это не продуктивно и не дальновидно. Умение расставлять приоритеты и отсеивать зёрна от плевел — важнейший навык. Если задача не требует срочного решения, она идёт в бэклог. А ещё учимся говорить "нет" там, где это необходимо.
🟢 удобное рабочее место (настроенная под себя IDE и горячие клавиши — тоже про это). Всё нужное должно быть под рукой и перед глазами (несколько экранов — ван лав даже для системного аналитика). Рутина не должна отнимать много времени! Чем неудобнее пространство вокруг нас, тем больше шансов сместить фокус внимания и "зависнуть".
🟢 автоматизируем всё, что возможно. Пишем небольшие скриптики, облегчающие рутину, используем gpt, там где это приемлимо (например, вам надо составить ddl-код для данных, получаемых с какого-нибудь открытого api — просто скормите json-ответ и доку gpt, к чёрту копирования)
🟢 используем технику Pomodoro, о которой я уже писала здесь.

Что советуют ещё:
🟡крепкий качественный сон — моя мечта последние 5 лет 😅 высыпаться реально помогает;
🟡планирование задач на день — стараюсь практиковать, но пока чаще получается, что держу всё в голове, тут есть над чем работать;
🟡мелкие-быстрые задачи решать сразу же, не держа их в голове, забивая память. Просто берём и делаем. Я же люблю порой попрокрастинировать и пооткладывать скучное-быстрое на "потом успею".

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

А что помогает вам?

#soft_skills
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
NULL_COUNT и NULL_PERCENT для мониторинга качества данных в Snowflake

Я уже много раз упоминала, что от данных в DWH не будет никакого смысла, если мы не сможем им доверять. Что нужно для доверия? Регулярный мониторинг за качеством данных. Data quality должно пронизывать все этапы жизни данных в хранилище. И об этом говорить мы будем ещё очень много. Но сегодня я хочу рассказать о классных плюшках в Snowflake, которые чуть упрощают нам некоторые проверки.

В Snowflake есть много встроенных встроенных метрик помогающих отслеживать качество данных. И функция SYSTEM$DATA_METRIC_SCAN как раз одна из них. Она упрощает получение метрик качества данных без необходимости писать сложные запросы.

Например, функция NULL_COUNT возвращает строки в таблице, которые содержат значение NULL в определенном столбце. А NULL_PERCENT помогает посчитать % NULL-значений от общего количества строк. Почему не использовать выборку по условию WHERE column_name is NULL? В рамках разовых точечных расчётов, использование этих встроенных метрик не даёт заметного прироста производительности. А вот вывести несколько метрик разом по одной таблице или одним запросом по нескольким быстрее-проще, используя функции.

Какие метрики можно посмотреть в рамках SYSTEM$DATA_METRIC_SCAN?
🟢 NULL_COUNT — количество NULL-значений в поле
🟢 NULL_PERCENT — % NULL-значений от общего количества строк
🟢 BLANK_COUNT — количество пустых строк (для текстовых полей)
🟢 BLANK_PERCENT — % пустых строк от общего количества строк
🟢 DUPLICATE_COUNT — количество дублей поля (не целиком строки)

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

CREATE TABLE orders (
order_id NUMBER,
customer_id NUMBER,
product_id NUMBER,
order_date DATE,
delivery_date DATE,
amount NUMBER,
promo_code STRING
);

-- Для нашего примера заполним её тестовыми данными:
INSERT INTO orders VALUES
(1, 100, 500, '2024-01-01', '2024-01-03', 1500, NULL),
(2, 101, 501, '2024-01-01', NULL, 2000, 'WINTER24'),
(3, 102, 502, '2024-01-02', '2024-01-04', 1800, ''),
(4, NULL, 501, '2024-01-02', NULL, 2000, NULL);

-- Посчитаем какой % NULL-значений в поле customer_id и % пустых строк в promo_code
SELECT
SNOWFLAKE.CORE.NULL_PERCENT(SELECT customer_id
FROM orders) as null_percent_customer_id,
SNOWFLAKE.CORE.BLANK_PERCENT(SELECT promo_code
FROM orders) as blank_percent_promo_cd;

--Выведем все строки с BLANK-значениями в поле promo_code
SELECT *
FROM TABLE(SYSTEM$DATA_METRIC_SCAN(
REF_ENTITY_NAME => 'orders',
METRIC_NAME => 'snowflake.core.blank_count',
ARGUMENT_NAME => 'promo_code'
));


Результат первого запроса покажет:

| null_percent_customer_id | blank_percent_promo_cd |
|--------------------------|------------------------|
| 25 | 33,33 |


А второй выведет строки таблицы с promo_code = '' целиком.

Как всё это применять?
🔘определение пороговых значений для NULL и BLANK в критичных колонках
🔘настройка регулярного мониторинга
🔘создание алертов на основе результатов проверок

Использование этой функции (с умом) позволяет нам быстро и просто находить аномалии в данных и реагировать на проблемы до того, как они повлияют на бизнес-процессы. Но даже если вы не используете Snowflake, не забывайте строить метрики качества другими методами.

#snowflake #data_quality
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42
Не ошибается тот, кто ничего не делает?

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

У тех, кто только вкатывается в профессию, порой существует ошибочное представление, что люди с высокими грейдами не ошибаются. Но ошибаться нормально каждому — в конце концов, мы не запрограммированные роботы (да и те не застрахованы от ошибок, ведь их создавали такие же люди 😉).

На мой взгляд, об уровне специалиста говорит не факт наличия или отсутствия ошибок (хотя после утренних алертов я вновь засомневалась на свой счёт 😆). Куда важнее реакция после.

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

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

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

Ошибаться не стыдно, стыдно делать вид, что виноват не ты, а кто-то другой.

#soft_skills
Please open Telegram to view this post
VIEW IN TELEGRAM
👍65💯1
Материализованные представления: ускоряем аналитику

Материализованные представления (Materialized Views, MV, матвью) — способ ускорить выполнение аналитических запросов за счет предварительного вычисления и сохранения данных.


Чтобы понять матвью, давайте вернёмся на шаг назад и вспомним, что такое вью (view, V, представление). Представление — это виртуальные таблицы, которые хранят текст SQL-запроса и запускаются на лету. Они не сохраняют сами данные (в некоторых бд могут кешироваться в рамках сеанса до изменения источников).

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

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

Рассмотрим пример создания MV для Snowflake:

CREATE MATERIALIZED VIEW sales_summary_mv AS
SELECT
region,
category,
SUM(revenue) AS total_revenue,
COUNT(*) AS transaction_count
FROM sales
GROUP BY region, category;


Как происходит синхронизация данных?
Чаще всего MV автоматически обновляются при изменении исходных данных. Однако частота и способ обновления зависят от СУБД:
— Snowflake: обновляются инкрементально, снижая нагрузку на хранилище.
— PostgreSQL: обновление требует явного выполнения команды REFRESH MATERIALIZED VIEW, что добавляет ручной работы.
— Oracle: поддерживаются как полные, так и инкрементальные обновления в зависимости от настроек.
— Microsoft SQL Server: MV называются индексированными представлениями и обновляются автоматически, но с ограничениями на типы запросов.

Когда использовать MV
🟢 один и тот же сложный запрос выполняется многократно на большом объёме данных;
🟢 исходные данные обновляются редко, а аналитика выполняется часто;
🟢 нужен быстрый доступ к данным с минимальной задержкой;
🟢 есть достаточно места для хранения данных.

Когда не стоит использовать MV
🟣 запросы редкие или исследовательские (ad hoc) — тогда затраты перевешивают выгоду;
🟣 ограничено место для хранения (ведь данные сохраняются физически);
🟣 данные обновляются слишком часто — материализованные представления необходимо часто обновлять, что может привести к дополнительным накладным расходам (актуально не для всех систем);
🟣 запросы содержат конструкции, не поддерживаемые MV (зависит от БД).

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

#dwh
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1🔥1
Как открытые вопросы помогают понимать бизнес

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

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


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

Звучит просто, но давайте разберём на примерах.

— Какие данные вы хотите анализировать?
Часто заказчики начинают с обобщений, например, "Нам нужны все данные". Чтобы понять что же именно от нас хотят, можем спросить:
– Какие процессы или метрики для вас наиболее важны?
– Какие системы предоставляют данные для этих метрик?
– Есть ли данные, которые уже не актуальны или которыми не пользуются?

— В каком разрезе нужны данные?
Чтобы данные действительно помогали бизнесу, нужно понимать, в каких разрезах их нужно подавать:
– Какие временные рамки вас интересуют (дни, недели, месяцы)?
– Какие параметры важны (регионы, продукты, каналы продаж)?
– Есть ли специфические сегменты, которые требуют особого внимания?

Пример:
Плохо: "Нужно ли делить данные по времени?"
Хорошо: "Какой временной разрез наиболее полезен для ваших целей?"

— Как вы хотите использовать эти данные?
Чтобы понять цель запроса, можно обсудить ключевые моменты:
– Какие отчёты вы хотите получить?
– Какие решения вы планируете принимать на их основе?
– Можете ли вы показать примеры отчётов, которые сейчас вас не устраивают и чем?

— Какие есть ограничения?
Здесь можем уточнить моменты, которые помогут понять возможные ограничения или сложности:
– Есть ли ограничения по срокам?
– С какой периодичностью нужно обновлять данные, чтобы они оставались актуальными для отчетов? Какие процессы требуют более частого обновления, а для каких можно использовать данные с задержкой?
– Какие бизнес-процессы зависят от этих данных?

— Что делать, если данные противоречат друг другу?
Работая с хранилищем, аналитики часто сталкиваются с конфликтами в данных. Можем спросить:
– Как определять достоверность данных?
– Кто принимает решение при возникновении противоречий?

Пример:
Плохо: "Данные из разных источников не совпадают?"
Хорошо: "Бывали ли случаи, когда данные из систем не совпадали? Как определяется источник правды?"

— Как могут измениться требования в будущем?
Требования к данным меняются со временем. Не всё очевидно заранее, но открытые вопросы помогут заранее предусмотреть будущие доработки:
– Планируете ли вы подключать новые источники данных?
– Какие дополнительные метрики могут понадобиться?

Как задавать открытые вопросы?
Чтобы вопросы работали, следуйте нескольким правилам:
*️⃣ Начинайте с "Почему?", "Как?", "Что?", "Какие?", ...
*️⃣ Избегайте формулировок, которые допускают ответ "да" или "нет".
*️⃣ Стройте вопросы так, чтобы они побуждали к диалогу. Дайте собеседнику возможность пообщаться и поделиться деталями. Это будет полезно и для нас, и для него. Ведь разговор предполагает дополнительное размышление.

Открытые вопросы — это инструмент, который помогает не только уточнить требования заказчика, но и наладить продуктивное взаимодействие. Важно не просто сделать крутое хранилище (которым никто не пользуется), но и отвечающее ожиданиям пользователей. Чем больше информации мы соберём на начальном этапе общения, тем меньше доработок понадобится в будущем.

#soft_skills
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍1
ETL и ELT: разбираемся вместе

Больше года назад я писала короткую заметку что такое ETL-процессы, но до подробного разбора руки так и не дошли.

Тем временем Вова Никулин, автор канала Lost in Data классно раскрыл эту тему со стороны дата-инженера. Вот его пост про основы ETL: тык. В нём простое объяснение как работает ETL и как реализовать его с помощью Python и SQL. Мега полезно, если вы только начинаете погружаться в тему.

А в свежем посте он развивает тему, объясняя разницу между ETL и ELT и их связь с Data Lake. Ещё вы узнаете, что такое Data LakeHouse, как гибридный подход меняет работу с данными и о том, почему в современном мире разница между ETL и ELT постепенно размывается (спойлер: всё также мы говорим ETL, хотя по факту давно перешли на ELT и EtLT).

Рекомендую канал Lost in Data, если вы хотите развиваться в области хранилищ данных, аналитики или автоматизации 🚀
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥2
Недавно столкнулась с хейтом к этому посту. Комментатор возмущался, что "понаберут с улицы" и "как вообще может быть связаны ТЗ и sql". Вот что случается, когда смотришь на мир слишком узко и сталкиваешься с вещами вне своей специфики.

Связь, на самом деле, очевидна, если понимать, как работают процессы в хранилище данных. ТЗ описывает не только саму задачу, но и контекст: что именно нужно сделать, с какими ограничениями и какие бизнес-требования лежат в основе (т.е. зачем вообще мы это делаем, согласитесь – важное понимание). SQL, в свою очередь, — это лишь один из возможных инструментов реализации описанного в ТЗ.

Безусловно, есть компании и команды, где просто физически нет возможности (а порой и необходимости, если всё делает 1 человек) писать ТЗ. Но у нас в хранилище этот процесс работает чётко: крупные задачи передаются от системных аналитиков дата-инженерам именно через ТЗ. Мы продумываем решение, экспериментируем, описываем его и только потом передаём на реализацию.
Речь не о каких-то мелких правках, а о чём-то более масштабном. Например, о загрузке данных с новых источников новым методом (у нас дата-инженеры занимаются только разработкой, без исследования самих данных) или доработке текущих и разработке новых фреймворков.

К примеру, при подключении нового API-источника системный аналтик сначала анализирует, как меняются данные со временем, какие поля обязательны, какими методами забирать те или иные сущности, какие ограничения накладывает сам API, и где могут возникнуть потенциальные проблемы. После этого он описывает метод загрузки сущностей в виде ТЗ и передёт его (после ревью, конечно) дата-инженерам, которые уже занимаются разработкой технической части: настройкой пайплайнов, написанием ETL-скриптов, внедрением методов обработки и трансформации. Т.е. реализацией.

И вот здесь я вижу огромную ценность доступной и поддерживаемой документации. Говорю это, исходя из своего опыта. Сейчас мне приходится работать с горой незадокументированного легаси, которое создавалось годами в условиях ограниченных ресурсов, правилось ASAP-требованиями и чаще всего не имеет описаний ни в коде, ни документации. Даже скромное ТЗ на этапе разработки, могло бы помочь понять, какие изменения вносились и зачем. Теперь же приходится тратить время (очень много времени) на разбор неочевидных решений.

Моё имхо: без документации слишком много зависит от устных договорённостей. Это не отслеживаемо, не поддерживаемо и не безопасно — т.е. огромный риск, особенно если кто-то из ключевых сотрудников покинет проект.

А как у вас? Есть ли в вашей компании практика написания ТЗ или всё держится на неформальных договорённостях и тасках в jira?

#документация
🔥6👍2
Happy New Year 🎄

В 2025 хочется пожелать каждому думать больше о себе, а не о чужом «успешном успехе». Сравнивать себя только с собой вчерашним и расти относительно себя. И, конечно, берегите здоровье. Это ваше лучшее вложение и актив.

Пусть 2025 год будет интересным и добрым 🥳 остальное приложится, если захотите 👍
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍8🔥5🤗1
2025/07/08 20:25:35
Back to Top
HTML Embed Code: