Data Analysis / Big Data
2.73K subscribers
662 photos
4 videos
2 files
3.05K links
Лучшие посты по анализу данных и работе с Big Data на русском и английском языке

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels
Download Telegram
Как встроить LLM-анализ CSV в Airflow 3

Опрос Airflow содержит 5 856 строк и 168 столбцов. Для анализа собрали два DAG: интерактивный и плановый. В первом LLM переводит подтверждённый аналитиком вопрос в SQL, sqlglot пропускает только SELECT, а DataFusion выполняет запросы по CSV.

Плановый DAG ежемесячно скачивает свежий CSV, сверяет его схему с эталоном, выполняет запрос и отправляет отчёт. Если столбец удалили или переименовали, пайплайн останавливается до запуска SQL.

Схемы DAG, операторы common.ai и код подготовки CSV можно использовать как основу аналитического пайплайна.
Как ClickHouse ускоряет JOIN без ручной перестройки SQL

В ClickHouse 26.4 JOIN на TPC-H SF100 выполнялись в 26 раз быстрее, чем в 22.4, без специальных настроек.

Runtime-фильтр заранее отбрасывает строки без совпадений, снижая время и пиковую память. Статистика по столбцам помогает оптимизатору выбрать порядок соединений: в шеститабличном запросе время сократилось с 3903,7 до 2,7 секунды.

В разборе оптимизаций JOIN есть SQL-примеры и планы EXPLAIN для проверки на своих запросах.
Как Kubeflow SDK переносит обучение модели с ноутбука в Kubernetes

Функцию обучения на Python можно запускать локально, в контейнере или в Kubernetes без переписывания кода: достаточно сменить настройку среды.

SDK сериализует функцию и зависимости, создаёт ресурс TrainJob и передаёт его оператору Kubernetes. Для распределённого запуска не нужно вручную собирать YAML-манифесты.

Архитектура SDK и пример распределённого обучения показывают, как единый Python-интерфейс связывает подготовку данных, обучение и подбор гиперпараметров.
Почему 99% попаданий в кэш почти в 10 раз быстрее 90%

На 10 000 чтений рост hit rate с 90% до 99% оставляет не 1 000, а 100 обращений к базе. В эксперименте время сократилось с 199,3 до 20,1 мс. Причина в том, что основную цену задают промахи: попадание лишь возвращает сохранённый результат, а промах запускает SQL-запрос.

Измерения на четырёх уровнях hit rate помогают раздельно оценить нагрузку на БД и задержку. Конкретное ускорение зависит от стоимости обоих путей: локальная Java-карта отвечает за наносекунды, а Redis добавляет сетевой запрос.

У ускорения есть цена. TTL в 300 мс дал 71 устаревший ответ из 83 при изменении значения десять раз в секунду. Кэш без лимита занял 70 МБ на 60 000 записей; ограничение до 1 000 недавних записей снизило объём до 8 МБ. Поэтому следить стоит не только за hit rate, но и за числом промахов, свежестью данных и лимитом памяти.
☃1✍1⚡1
Как DuckDB ускоряет чтение Parquet из S3

В тесте TPC-H Q6 запрос к Parquet-файлу размером около 22 ГБ выполнился за 2,844 секунды на DuckDB v2.0.0-dev вместо 8,230 секунды на стабильной v1.5.5. Данные читались напрямую из S3 без файлового кеша.

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

Глубину предзагрузки задаёт read_ahead_depth: значение N ограничивает очередь N заданиями, 0 отключает предзагрузку, а режим по умолчанию подстраивает её под доступную память. Для своего озера данных стоит проверить предварительную сборку на типичных файлах и сравнить время запроса, загрузку сети и расход памяти. Схема очереди и условия бенчмарка помогут воспроизвести эксперимент.
Как Meta удвоила эффективность обучения рекомендательной модели GEM

За 12 месяцев Meta в четыре раза увеличила вычисления при обучении GEM и подняла эффективность до 20–25% MFU: доли пиковой производительности GPU, занятой моделью.

История действий пользователя достигает десятков тысяч элементов. Выравнивание последовательностей тратило до 50% вычислений. JFA обрабатывает переменную длину без дополнения, а BlockAttention снижает стоимость внимания с O(L²) до O(L).

Схема оптимизации GEM предлагает порядок профилирования: сначала ядра, точность и память, затем обмен данными, балансировка нагрузки и топология сети.
Как 20–100 запросов в секунду перегрузили Elasticsearch в Zalando

Внутреннее приложение отправляло фасетные запросы: Elasticsearch строил агрегации по SKU, уникальному идентификатору товара. Из-за множества уникальных значений даже небольшой поток параллельных запросов создавал тяжёлую нагрузку. Синтаксис был корректным, а 20–100 запросов в секунду терялись на фоне тысяч обычных.

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

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

Два рентгеновских снимка 512 × 512 могут показывать разные физические области: масштаб пикселя хранится в DICOM. Перед обучением нужно удалить идентификаторы, учесть положение пациента и пересчитать масштаб после изменения размера. Разбор пути снимка до предсказания содержит ноутбук с pydicom, NumPy и OpenCV.

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

Для классификации нужна метка снимка, для детекции — область, для сегментации — маска. Модель проверяют на данных другой больницы и оценивают не только перекрытие, но и форму находок.
Почему 1000 файлов на процесс в PostgreSQL не жёсткий лимит

max_files_per_process по умолчанию равен 1000. Это размер кэша открытых дескрипторов, а не порог ошибки. Когда пул заполнен, бэкенд закрывает давно не использованный файл и открывает нужный. Запрос работает, но тратит время на системные вызовы.

В PostgreSQL 18.6 таблица из 3000 разделов создала 6000 файлов. При значении 8192 повторное сканирование обошлось без open() и ускорилось примерно на 8%: со 180 до 165 мс. Данные уже были в shared_buffers.

Одной настройки мало: systemd даёт процессу мягкий лимит 1024. Сначала посчитайте файлы в каталоге базы и увеличьте LimitNOFILE, затем задайте пул с запасом и перезапустите PostgreSQL. В PostgreSQL 18 ориентируйтесь на весь сервер: воркеры асинхронного ввода-вывода обслуживают все бэкенды.
Как в Zalando сократили состояние Flink на 75%

В пайплайне обогащения товарных данных цепочка SQL JOIN раздула состояние Flink до 235–245 ГБ. Каждый независимый оператор хранил собственную копию входных и промежуточных записей. Часовые снимки загружали процессор на 100% почти на 12 минут, увеличивали задержку и провоцировали перезапуски.

Команда объединила входящие потоки в DataStream[BaseEvent], сгруппировала события по SKU и заменила цепочку JOIN одной KeyedProcessFunction. Данные каждого товара теперь лежат в одном ValueState: событие обновляет нужные поля, а записи со старой временной меткой отбрасываются до записи состояния.

Переход на собственный MultiStreamJoinProcessor уменьшил состояние до 56 ГБ, а восстановление после перезапуска сократил с 12–20 до 4–5 минут. Полезный повод проверить, не дублируют ли последовательные stateful JOIN промежуточные данные в ваших Flink-задачах.
Как Apache Celeborn сохраняет shuffle-данные Spark при потере исполнителей

Spot-инстансы могут отключить за две минуты. Если Spark хранит shuffle-данные на локальном диске исполнителя, потеря узла запускает повторное вычисление стадий.

Apache Celeborn выносит shuffle в отдельный кластер: исполнители отправляют блоки общим worker-узлам, поэтому их можно заменять без потери промежуточных данных. Каждый раздел shuffle реплицируется ещё на два worker-узла.

Схема развёртывания для EMR on EC2 и EMR on EKS включает настройки Spark и мониторинг через Prometheus и Grafana.
❤2
Как ограничить память GROUP BY в ClickHouse при высокой кардинальности

22,82 GiB против 9,57 GiB пиковой памяти: такой результат даёт max_bytes_before_external_group_by в эксперименте с высококардинальной группировкой. Когда объём промежуточных данных достигает заданного порога, ClickHouse продолжает агрегацию с использованием диска. Цена экономии памяти: время запроса выросло с 9,433 до 13,930 секунды.

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

Разбор высокой кардинальности в ClickHouse поможет выбрать компромисс между памятью и скоростью, а также спроектировать хранение атрибутов под реальные запросы.
PySpark завис на 99%: как найти и устранить перекос данных

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

В Spark UI сравните максимальные Duration, Shuffle Read Size и Spill с медианой. Разница в десятки раз укажет на перекос. Затем посчитайте строки по ключам.

В разборе для Spark 3.5 советуют включить AQE: он дробит перекошенные партиции при соединении. Для малой таблицы используйте broadcast join, а для горячих ключей — salting, добавляющий суффиксы и распределяющий строки по партициям.
Как подготовить Parquet для быстрых запросов Power BI Direct Lake

На столбце из 142 млн строк запись encoding_stats в футере Parquet сократила первое обращение с 10 857,5 до 689,3 мс. VertiPaq выбрал быстрый путь после подтверждения словарного кодирования в метаданных.

Direct Lake загружает только затронутые запросом столбцы. Без словарного кодирования значения приходится декодировать и хешировать заново.

Эксперименты с DuckDB и delta-rs рекомендуют 2–6 млн строк на группу, словарное кодирование столбцов и сортировку по полям фильтров. Результат измеряйте на холодном и прогретом кеше.
Как выявить перекос долей выборки в A/B-тесте с NumPy и SciPy

В тесте на миллионе пользователей группы 502 470 и 497 530 кажутся равными, но для плана 50/50 это почти пять стандартных отклонений.

Такой перекос называют Sample Ratio Mismatch, или SRM. Его ищут χ²-тестом: сравнивают фактические размеры групп с плановыми долями. Достаточно счётчиков, NumPy и scipy.stats; метрика теста не участвует.

Если SRM сработал, сначала проверьте логирование и фильтрацию участников, затем оценивайте эффект. Код проверки и симуляция потери пользователей показывают, почему малый перекос опасен на большой выборке.
Как согласовывать JSON-события в DuckDB без Python

В CDC-потоке событие часто меняет одно-два поля. В DuckDB v2.0 json_merge_patch_diff вычисляет патч между старым и новым состоянием, а json_merge_patch восстанавливает документ.

json_deep_merge объединяет JSON из разных источников, сохраняя исходное значение при JSON null. Для дедупликации json_normalize сортирует ключи перед хешированием.

Примеры SQL и тест на 500 000 синтетических CDC-событий
Как Zalando проверяет качество поиска до запуска нового рынка

В 2025 году Zalando выходила в Люксембург, Португалию и Грецию. Данных о запросах и кликах ещё не было, поэтому качество поиска заранее оценивали с помощью LLM-судьи.

Пайплайн проверки релевантности берёт запросы действующих рынков: NER-модель выделяет атрибуты, а похожие запросы переводят на язык нового рынка.

Airflow запускает получение выдачи в Kubernetes, затем GPT-4o оценивает товары по шкале от 0 до 4 с учётом описания и изображения. Низкие оценки помогают найти ошибки в товарных данных, атрибутах и ранжировании.

Кеш хранит товары и оценки пар «запрос — товар», поэтому после исправлений прогон можно повторить без лишних обращений к API.
Как инкрементальный ETL в Apache Hudi сокращает повторную обработку данных

Если таблица на 10 ТБ получает 50 ГБ изменений в час, полный пересчёт читает все 10 ТБ. Инкрементальный пайплайн берёт только дельту: объём чтения сокращается в 200 раз.

Apache Hudi читает изменения после сохранённой контрольной точки. Запрос возвращает последнее состояние изменённых записей, а CDC-журнал — каждую операцию до и после изменения.

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

В тесте PostgreSQL 17.10 поиск по lower(customer_email) занимал 0,21 мс без RLS и 34–45 мс с политикой доступа. Это результат для крупнейшего клиента: около 267 тысяч строк в таблице почти на 2 млн записей.

Составной индекс использовался только для tenant_id, а условие по email стало фильтром. Причина в правилах RLS: функция lower() не помечена как leakproof, поэтому её нельзя свободно применять к строкам до проверки доступа.

В этом сценарии помогла сохранённая вычисляемая колонка с email в нижнем регистре и индексом по паре «клиент, email»: время вернулось к 0,25 мс. Замеры сделаны с прогретым кэшем. Проверяйте план под ролью приложения: владелец таблицы обычно обходит RLS.

Замеры, планы и варианты политик
Polars: как отличить медленный JOIN от ожидания данных

В примере профилирования Polars запрос выполнялся около 5 секунд, а CPU-время JOIN составило примерно 103 мс. Основным ограничением было чтение из S3.

Профилировщик показывает логический и физический планы, потоки строк и прогресс узлов. Для локального запроса нужно установить polars_cloud и включить pl.Config.enable_monitoring(). Возможность описана для streaming- и distributed-движков.

Запрос исполняется на вашей инфраструктуре; планы и телеметрия передаются в платформу Polars Cloud. Там можно смотреть текущие и завершённые запросы, находить дорогие операции и проверять, насколько рано применяются фильтры.

Такой профиль помогает выбрать, что оптимизировать первым: загрузку данных, JOIN или агрегацию.

Подключение и разбор профиля Polars
Когда DuckDB хватает для ETL вместо Spark

В примере AWS задание на DuckDB выполнилось примерно за 56 секунд, а эквивалентное на Spark — за 117. Оба запускались в Glue 6.0 с конфигурацией 2 DPU и вернули 1176 строк.

DuckDB работает внутри одного воркера: читает Parquet из S3, выполняет SQL-преобразования и записывает результат в S3 Tables через Iceberg REST catalog. Выходную таблицу можно запрашивать из Athena.

Для небольших регулярных заданий время запуска и накладные расходы движка могут заметно влиять на итог. Здесь DuckDB уложился в минимальную минуту тарификации, а Spark потребовал две.

Это замер одного сценария. Для своего ETL сравните объём входных данных, сложность JOIN, доступную память и полное время задания.

Код пайплайна и условия сравнения