400 subscribers
229 photos
47 videos
11 files
309 links
Data Engineering Technologies.
SQL, Python, Kafka, Spark, Pandas, Airflow, Clickhouse, Greenplum, Postgres, dbt

Буст канала тут - https://t.me/boost/data_engi
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
figure.ai запартнёрились с OpenAI

Как тебе такое, Сара Коннор?
🆒4
📎 Postman и паттерны проектирования API

Команда Postman Open Technologies собирает информацию о стандартах, отраслевых форматах и спецификациях, открытых API.

Каталог практик и паттернов оформлен как рабочее пространство Postman

На текущий момент там описаны следующие паттерны:
🟡 Форматы данных:
🔵Коды стран (ISO 3166)
🔵Коды валют (ISO 4217)
🔵Дата, время и временные промежутки (ISO 8601)
🔵Числа с десятичными дробями
🔵Кастомные заголовки HTTP
🔵Расширенное описание ошибки (RFC 9457 - кстати, очень хороший формат для передачи смысла ошибки HTTP)

🟡Управление кэшированием:
🔵Параметр Cache-control
🔵Параметр Etag
🔵Параметр Expires

🟡Фильтрация:
🔵Параметры поискового запроса
🔵Точное соответствие
🔵Диапазон значений поля
🔵Выбор полей для ответа

🟡Пагинация:
🔵Заголовки page and per_page (rfc 5988)
🔵Курсор / NextRecordKey
🔵Параметры Limit и Offset

🟡Сортировка:
🔵По одному полю - параметры sort_by, sort_order
🔵По нескольким полям

🟡Версионирование:
🔵На уровне URL API
🔵На уровне отдельного ресурса
🔵Через заголовок Accept-Version
🔵Через заголовок Accept

🟡Информация:
🔵Контакты разработчиков
🔵Лицензия
🔵Условия использования
🔵Заголовок Sunset
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3🆒2
IMG_20240315_000134_555.png
971 KB
👩‍💻 SQL CheatSheet

Шпаргалка по SQL

JOIN, IN, LIKE, BETWEEN, ORDER BY и другое, ботай!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
⚡️ Выкатили новую версию 🖼️ Airflow 2.8.3


📦 PyPI

📚 Docs

🛠 Release Notes

🐳 Docker Image:
docker pull apache/airflow:2.8.3

#airflow
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
😁7
😁3
👩‍💻 Распространённые ошибки составления SQL запросов

Использование SELECT *

❤️‍🩹 Проблема: Выбор всех колонок с помощью SELECT * приводит к передаче ненужных данных, увеличению использования памяти и снижению производительности запросов.
✔️ Решение: Укажи в операторе SELECT только необходимые колонки.

〰️ Пример проблемы
SELECT * FROM employees;
〰️ Улучшенный запрос
SELECT employee_id, first_name, last_name FROM employees;
Отсутствие индексов

❤️‍🩹 Проблема: Отсутствие индексов может привести к полному сканированию таблицы и снижению производительности запросов.
✔️ Решение: Создай и используй индексы для часто используемых в выражениях WHERE колонок.

〰️ Создание индекса
CREATE INDEX idx_last_name ON employees(last_name);
〰️ Использования индекса в запросе
SELECT * FROM employees WHERE last_name = 'Smith';
Чрезмерное использование подзапросов

💔 Проблема: Подзапросы могут работать медленнее, чем JOIN, особенно при работе с большими наборами данных.
✔️ Решение: Используй JOIN, когда это возможно, а подзапросы оставь для ситуаций, в которых они более эффективны.

〰️ Пример проблемы (подзапрос)
SELECT department_name FROM departments WHERE department_id IN (SELECT department_id FROM employees);
〰️ Улучшенный запрос (JOIN)
SELECT DISTINCT d.department_name FROM departments d JOIN employees e ON d.department_id = e.department_id;
Неэффективные JOIN

❤️‍🩹 Проблема: Выбор неправильного типа JOIN (например, Cartesian JOIN) или неправильное указание условий соединения может привести к неправильным результатам или замедлению запросов.
✔️ Решение: Разберись в различных типах JOIN (INNER, LEFT, RIGHT, FULL) и используй их по назначению.

〰️ Пример проблемы (Cartesian JOIN)
SELECT * FROM employees, departments;
〰️ Улучшенный запрос (INNER JOIN)
SELECT e.employee_name, d.department_name FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id;
Неиспользование выражений WHERE

❤️‍🩹 Проблема: Отсутствие фильтрации данных с помощью выражений WHERE может привести к запросу ненужных данных.
✔️ Решение: Всегда включайте выражения WHERE, ограничивающие набор результатов.

〰️ Пример проблемы (без выражения WHERE)
SELECT * FROM orders;
〰️ Улучшенный запрос (с выражением WHERE)
SELECT * FROM orders WHERE order_date >= '2023-01-01';
Игнорирование планов выполнения запросов

💔 Проблема: Игнорирование планов выполнения запросов может привести к упущенным возможностям оптимизации.
✔️ Решение: Используй такие инструменты, как EXPLAIN, для анализа планов выполнения и внесения необходимых оптимизаций.

〰️ Просмотр плана выполнения
EXPLAIN SELECT * FROM products WHERE category = 'Electronics';
Отсутствие оптимизации больших наборов данных

❤️‍🩹 Проблема: Запросы, хорошо работающие с небольшими наборами данных, могут плохо работать с большими объёмами данных.
✔️ Решение: Реализуй такие стратегии, как пагинация, разбиение данных на разделы и оптимизация индексов для больших наборов данных.

〰️ реализация пагинации
SELECT * FROM products LIMIT 10 OFFSET 20;
Повторяющиеся агрегации

❤️‍🩹 Проблема: Повторение одних и тех же агрегаций в нескольких частях запроса может быть неэффективным.
✔️ Решение: Используй CTE (Общие табличные выражения) для хранения промежуточных результатов и избегай лишних вычислений.

〰️ Пример проблемы (повторяющаяся агрегация)
SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department;
〰️ Улучшенный запрос (с CTE)
WITH DepartmentSalaries AS (
SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department
)
SELECT * FROM DepartmentSalaries;
Неадекватная обработка ошибок

💔 Проблема: Неправильная обработка ошибок может привести к сбоям в работе приложения или неправильным результатам.
✔️ Решение: Реализуйте надлежащую обработку ошибок в SQL запросах или в коде приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥8
〰️ Пример обработки ошибок в SQL (MySQL)
BEGIN;
-- SQL выражение
IF some_condition THEN
ROLLBACK; -- Откат транзакции при ошибке
ELSE
COMMIT; -- Коммит транзакции при успешном выполнении всех выражений
END IF;
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥4😁2
😁4
👩‍💻 Временная таблица в базе данных SQL

〰️〰️〰️〰️〰️〰️〰️〰️

🔜 Временная таблица SQL (temp table) — это такая таблица, которую ты создаёшь и используешь в контексте определённого сеанса или транзакции в СУБД. Она предназначена для хранения временных данных, которые понадобятся на короткое время и не требуют постоянного хранения.

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

🔜 Чтобы создать временную таблицу, можешь использовать инструкцию CREATE TABLE с ключевым словом TEMPORARY или TEMP перед именем таблицы:

CREATE TEMPORARY TABLE my_temp_table (
id INT,
name VARCHAR(50),
age INT
);
Детали:

🔜 Инструкция CREATE TEMPORARY TABLE используется для создания временной таблицы.

🔜 my_temp_table — это имя, которое присваивается временной таблице. Имя можно выбрать любое.

🔜 Внутри круглых скобок мы определяем столбцы временной таблицы.

🔜 В примере временная таблица my_temp_table имеет три столбца: id типа INT, name типа VARCHAR(50) и age типа INT.

🔜 При необходимости ты можешь добавить дополнительные столбцы, указав их имена и типы данных.

🔜 Временная таблица автоматически удаляется в конце сеанса или при завершении сеанса.

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

🔜 Создаёшь временную таблицу с подмножеством данных

CREATE TEMPORARY TABLE subset_data AS
SELECT column1, column2, column3
FROM original_table
WHERE condition;
🔜 Анализируешь подмножества данных

SELECT column1, AVG(column2) AS average_value
FROM subset_data
GROUP BY column1;
🔜 Удаляешь временную таблицу

DROP TABLE subset_data;
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥5
👩‍💻 Повышение производительности запросов с использованием временных таблиц

〰️〰️〰️〰️〰️〰️〰️〰️

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

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

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

➡️ Создаёшь временную таблицу для хранения промежуточных результатов

CREATE TEMPORARY TABLE temp_results AS
SELECT column1, COUNT(*) AS count_value
FROM large_table
WHERE condition1
GROUP BY column1;
➡️ Используешь временную таблицу для оптимизации итогового запроса

SELECT column1, column2
FROM temp_results
WHERE count_value > 10
ORDER BY column1;
➡️ Удаляешь временную таблицу

DROP TABLE temp_results;
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
👩‍💻 Подготовка и преобразование данных во временных таблицах

〰️〰️〰️〰️〰️〰️〰️〰️

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

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

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

➡️ Создаёшь временную таблицу для подготовки данных

CREATE TEMPORARY TABLE staging_table (
id INT,
name VARCHAR(50),
quantity INT
);
➡️ Импортируешь и преобразовываешь данные в стейджинг таблицу

INSERT INTO staging_table (id, name, quantity)
SELECT id, UPPER(name), quantity * 2
FROM external_source;
➡️ Валидируешь и проводишь манипуляции с данными в стейджинг таблице

UPDATE staging_table
SET quantity = 0
WHERE quantity < 0;
➡️ Вставляешь преобразованные данные в таргет таблицу

INSERT INTO final_table (id, name, quantity)
SELECT id, name, quantity
FROM staging_table;
➡️ Удаляешь временную таблицу

DROP TABLE staging_table;
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
Forwarded from Хитрый Питон
Мы у себя в компании начали аккуратно переходить на новый менеджер пакетов uv (https://github.com/astral-sh/uv) и решил рассказать, как все идет.

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

Все сложности были при использовании нескольких индексов:
- политика разрешения зависимостей uv отличается от pip - это важно, когда используется свой индекс в добавок к pypi
- авторы решили не переиспользовать переменную окружения PIP_EXTRA_INDEX_URL - для uv надо задавать UV_EXTRA_INDEX_URL
- в UV_EXTRA_INDEX_URL лушче прописывать `/simple`-индекс, у меня сначала было не так, pip работал, а uv уже нет

Но какая же uv офигенно быстрая. Вот примеры двух наших разных проектов:

1. Внутренняя библиотека (меньше 20 зависимостей)
- pip-tools 4 минуты 7 секунд
- с uv 10 секунд

2. Большой старый монолит на Django (больше 100 зависимостей):
- с pip-tools 18 минут 19 секунд
- с uv 32 секунды (!!!)

В общем я очень доволен результатом и рекомендую как минимум посмотреть на эту тулзу.
😁2🆒2❤‍🔥1
👩‍💻 Кортежи


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

📌 Если хочешь явно узнать, является ли значение кортежа, да и любого другого объекта, фиксированным, можешь использовать встроенную функцию hash и сделать на её основе функцию is_fixed, например такую:

def is_fixed(obj) -> bool:
try:
hash(obj)
except TypeError:
return False
return True
#python #trix
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
👩‍💻 Кортежи


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

Пример, изначально два кортежа равны:

a = (1, 'data engi', [8, 9])
b = (1, 'data engi', [8, 9])

print(a == b)
Получим результат:

True

Но при внесении изменений в последний элемент кортежа b:

b[-1].append(10)

print(a == b)
Получим результат:

False
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥2🆒1
👩‍💻 Рекомендации при работе с PostgreSQL

▶️ Используй отдельные схемы для разных модулей

Скажем, тебе необходимо реализовать систему рассылки пуш-уведомлений на android-устройства клиентов. Ты пишешь сервис, который будет работать с FCM. Пишешь функции в своей БД, которые будут выдавать списки token-текст (да там много полей вообще).
Так вот, необходимо, чтобы такие ручки для разных модулей (бэкендов) лежали в отдельных схемах.

▶️ Используй группы ролей и назначай гранты именно на роли

Предположим, что ты реализовал пункт выше, теперь твой сервис должен подключаться к БД и крутить свои запросы. Но под каким пользователем? Не будет же он бегать под postgres или admin?)

▶️ Используй расширения

PostgreSQL — это мощная СУБД. Но и она не может быть универсальной. Не надо полагать, что всё делается штатными средствами PostgreSQL. Так-же не надо пробовать писать свои системы чего-либо.

▶️ Храни дататайм в timestamptz

Возьми за привычку в БД всегда хранить timestampTZ и когда-нибудь Тебе скажут большое спасибо за это.

▶️ Используй метрики

Пользуйся pg_stat_statements
Так-же рекомендую сразу установить расширения для мониторинга запросов (например pg_stat_statements)

▶️ В функциях лучше использовать CTE и длинные запросы, чем временные таблицы

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

▶️ Не делай партиции везде, где только можно

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

▶️ Не забывай делать дополнительную статистику

Да, когда планировщик не так представляет выхлоп — у тебя могут получиться очень медленные запросы.

▶️ Старайся не пихать всё в TOAST

Наверное сразу стоит добавить и тот пункт, что не надо хранить в TOAST, например json/text с дефолтным параметром хранения, аналитические данные.

#postgres
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥4
Forwarded from Записки kiriharu
В нашу жизнь проникает всё больше AI инструментов, поэтому делитесь в комментариях какими пользуетесь сами или о которых знаете.

Вот список из моих, юзаю практически каждый день:
- Очевидный ChatGPT
- Апскейлиг картиночек (старые мемы выглядят как новые!)
- Переводчик DeepL
- Поисковик Perplexity AI
- Нейросеть от Яндекса, которая кратко пересказывает содержимое статей и видео
- А вот тут мелкомягкие позволяют генерировать картиночки
- Вот тут я удаляю фон у фоточек
🆒4
📚 Книги по некоторым технологиям обработки данных
〰️〰️〰️〰️〰️〰️〰️〰️

📎 Spark: The Definitive Guide
В книге рассказывается, как использовать, развёртывать и поддерживать Apache Spark с помощью этого всеобъемлющего руководства, написанного создателями фреймворка кластерных вычислений с открытым исходным кодом.

📎 Hadoop. Подробное руководство
Книга, в которой подробно и доходчиво описаны все возможности Apache Hadoop.

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

📎 Kubernetes в действии
В книге подробно рассказывается о Kubernetes - софт Google с открытым исходным кодом для автоматизации развёртывания, масштабирования и управления приложениями, масштабированием и управлением приложениями с большими данными

📎 Cassandra The Definitive Guide: Distributed Data at Web Scale
В этом руководстве объясняется, как СУБД Cassandra обрабатывает сотни терабайт данных, поддерживая высокую доступность данных в нескольких центрах обработки данных

📎 MongoDB: полное руководство В этой книге подробно рассматривается MongoDB, мощная СУБД. Здесь ты сможешь узнать, как эта безопасная, высокопроизводительная система обеспечивает гибкие модели данных, высокую доступность данных и горизонтальную масштабируемость.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥6
👩‍💻 match/case

Для версий Python 3.10 и выше.

Деструктуризация с помощью образцов настолько выразительна, что иногда даже наличие единственной ветви case может сделать код проще. Гвидо ван Россум собрал коллекцию примеров match/case, один из которых назвал «Очень глубокий итерируемый объект и сравнение типа с выделением».

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

❤️‍🩹 Классическая версия:
 def write_value(self, value):
if isinstance(value, str):
self.simple_element("string", value)

elif value is True:
self.simple_element("true")

elif value is False:
self.simple_element("false")

elif isinstance(value, int):
if -1 << 63 <= value < 1 << 64:
self.simple_element("integer", "%d" % value)
else:
raise OverflowError(value)

elif isinstance(value, float):
self.simple_element("real", repr(value))

elif isinstance(value, dict):
self.write_dict(value)

elif isinstance(value, (bytes, bytearray)):
self.write_bytes(value)

elif isinstance(value, datetime.datetime):
self.simple_element("date", _date_to_string(value))

elif isinstance(value, (tuple, list)):
self.write_array(value)

else:
raise TypeError("unsupported type: %s" % type(value))
🔥 Версия с использованием match/case:
 def write_value(self, value):
match value:
case str():
self.simple_element("string", value)

case True:
self.simple_element("true")

case False:
self.simple_element("false")

case int():
if -1 << 63 <= value < 1 << 64:
self.simple_element("integer", "%d" % value)
else:
raise OverflowError(value)

case float():
self.simple_element("real", repr(value))

case dict():
self.write_dict(value)

case bytes() | bytearray():
self.write_bytes(value)

case datetime.datetime():
self.simple_element("date", _date_to_string(value))

case tuple() | list():
self.write_array(value)

case _:
raise TypeError("unsupported type: %s" % type(value))
#python #casematch
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
👩‍💻 Автогенерация первичного ключа

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

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

Автогенерацию первичного ключа часто называют автоинкрементом (autoincrement). Что переводится как автоматическое увеличение и напоминает операцию инкремента из программирования ++.

До определённого момента механизм автоинкремента был реализован в каждой СУБД разными способами. Это создавало проблемы при переходе от одной СУБД к другой и усложняло реализацию программного слоя доступа к БД.

Эта функциональность добавлена в стандарт SQL:2003, то есть довольно давно. И только в 2018 году PostgreSQL в версии 10 стал его поддерживать. Такой автоинкремент известен под именем GENERATED AS IDENTITY:
CREATE TABLE colors (
-- Одновременное использование и первичного ключа и автогенерации
id bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name varchar(255)
);

INSERT INTO colors (name) VALUES ('Red'), ('Blue');

SELECT * FROM colors;

-- id name
-- 1 Red
-- 2 Blue
Если удалить запись с id равным двум и вставить ещё одну запись, то значением поля id будет 3. Автогенерация не связана с данными в таблице. Это отдельный счётчик, который всегда увеличивается. Так избегаются вероятные коллизии и ошибки, когда один и тот же идентификатор принадлежит сначала одной записи, а потом другой.

Структура из документации:
column_name type GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY[ ( sequence_option ) ]
Please open Telegram to view this post
VIEW IN TELEGRAM
🆒5❤‍🔥1