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
Как поделиться Parquet через небольшой каталог DuckDB

Чтобы дать коллегам доступ к набору Parquet-файлов, можно подготовить DuckDB-файл только с представлениями. Он хранит запросы и имена отношений, а сами данные остаются в объектном хранилище.

В руководстве команды DuckDB создают VIEW над удалённым файлом и публикуют каталог по URL. Получатель подключает его в режиме READ_ONLY и обращается к представлениям как к таблицам.

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

Каталог не заменяет доступ к источникам: читателю нужны права и на DuckDB-файл, и на данные, на которые он ссылается. Для изменения опубликованного каталога редактируют локальную копию и загружают её заново. Скорость запросов зависит от сети и устройства Parquet-файлов.

#duckdb #dataengineering
Почему быстрый запрос ClickHouse ждёт лишний RTT

У клиента ClickHouse простой SELECT после простоя соединения занимал около 64 мс вместо 32 мс. Команда обнаружила дополнительный сетевой обмен, хотя вычисление запроса было быстрым.

В Native-протоколе клиент ждёт пакет EndOfStream. Перед ним сервер отправляет результат и служебные пакеты с логами, прогрессом и метриками. После простоя TCP уменьшает окно перегрузки: в него может не поместиться вся эта последовательность.

С TCP_NODELAY небольшие записи уходят сразу и создают много отдельных TCP-сегментов. Сервер исчерпывает окно и ждёт подтверждения клиента, прежде чем отправить остаток. Так появляется лишний RTT.

В разборе расследования проблему воспроизводят через Linux network namespaces. Исправление — собрать служебные пакеты в буфер и отправлять вместе. Число 32 мс относится к сети конкретного клиента; причина полезна для диагностики хвоста задержек после простоя.

#clickhouse #производительность
Как изменить партиции Spark Streaming и сохранить состояние

Число партиций stateful-запроса закрепляется в checkpoint. Поэтому изменение spark.sql.shuffle.partitions после перезапуска не перераспределяет уже накопленное состояние.

В разборе Databricks показана функция On-Demand State Repartitioning. Она доступна в Public Preview для Databricks Runtime 18+ с RocksDB state store.

Процедура требует остановки запроса: задайте новое значение spark.sql.streaming.stateStore.partitions и перезапустите обработку с прежним checkpoint. Система завершит незаконченный запланированный микробатч, если он есть, затем перераспределит состояние и продолжит поток.

Длительность операции видна в controlBatch.REPARTITION внутри метрик прогресса. Она зависит от объёма состояния, поэтому изменение стоит планировать на окно обслуживания. Такой подход позволяет подобрать параллелизм без сброса накопленных окон, агрегатов и данных дедупликации.

#spark #streaming
Как сохранить структуру HL7v2 при загрузке в Spark

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

В разборе Funke команда Databricks показывает парсер на Python и PySpark, который сохраняет эту иерархию в стандартных типах Spark. Нужные элементы можно извлекать через DataFrame API или SQL.

Пайплайн сначала записывает исходные сообщения и метаданные загрузки в bronze-таблицу raw_messages. Затем в silver-таблице parsed_messages появляется колонка hl7 с разобранной структурой. На её основе строят gold-таблицы под конкретные метрики.

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

#pyspark #dataengineering
Что внутри Iceberg-таблицы и как это проверить

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

В разборе команды DuckDB показан путь от каталога до строк. Каталог хранит указатель на актуальный JSON-файл метаданных. Тот ведёт к списку манифестов и самим манифестам в Avro, а дальше — к файлам данных и удалений.

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

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

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

#iceberg #duckdb
Polars 2.0: потоковое выполнение стало стандартным

В Polars 2.0 вызов collect() у LazyFrame по умолчанию использует потоковый движок. Это меняет и расход памяти, и некоторые свойства результата.

В описании релиза команда отдельно предупреждает о порядке строк: для JOIN, GROUP BY и ряда других операций он по умолчанию не гарантируется. Если порядок нужен, его следует запросить через maintain_order=True там, где параметр поддерживается.

Включена и начальная поддержка выгрузки промежуточных данных на диск. Она работает для сортировок, оконных функций и многих выражений. Такая поддержка для JOIN и GROUP BY на момент релиза ещё в планах.

По умолчанию выгрузка начинается примерно при 80% занятой RAM, бюджет диска — 64 ГБ. Обновление поэтому стоит проверять на своих тяжёлых запросах: сравнить память, место для временных файлов и порядок строк в результате. Больший объём данных ещё не означает, что любая цепочка операций сможет завершиться на ограниченной памяти.

#polars #dataengineering
Почему DISTINCT недостаточно для дедупликации во Flink

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

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

Есть и ловушка настройки: подсказка STATE_TTL в рассмотренной реализации применяется к JOIN и агрегациям, но игнорируется операторами Rank и Deduplicate. Для них время хранения задаётся параметром сессии.

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

#flink #streaming
Как Atlassian привела 44 млрд событий в день к общей схеме

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

В кейсе Atlassian события безопасности приводят к открытой схеме OCSF ещё до загрузки в хранилище. Схема представлена структурами Go, а преобразования проходят тесты и проверку на ограниченном потоке перед полным развёртыванием.

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

По данным кейса, стоимость загрузки снизилась на 80%. Один из примеров запросов после структурирования данных, партиционирования и Z-ORDER сократился примерно с 45 до 2–3 секунд.

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

#dataengineering #качество_данных
Как Spark загружает данные в Lakebase в обход основного сервера

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

В разборе архитектуры LTAP Databricks переносит построение страниц Postgres на исполнителей Spark. Каждый запускает изолированный экземпляр базы, создаёт свою часть данных и передаёт готовые страницы в хранилище Lakebase.

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

Во внутреннем тесте построение страниц для 1 ТБ заняло менее пяти минут. Этот замер не включает параллельное построение индексов.

Подход зависит от устройства Lakebase: вычисления и долговременное хранение разделены. Обычная отправка данных из Spark через JDBC в самостоятельный Postgres не даёт такого пути записи автоматически.

#spark #postgresql
🔥1
Как Ridgeline разделила свежие данные и многолетнюю историю

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

В разборе архитектуры Ridgeline свежие данные размещаются в ClickHouse. Часть поступает напрямую из учётных систем, часть реплицируется из Postgres через CDC.

Большие исторические выгрузки от новых клиентов обрабатывает Spark и сохраняет в Iceberg. Старые данные читаются через Iceberg-коннектор ClickHouse, когда нужны отчёту.

В быстром слое обычно остаются два–четыре года, а более длинная история хранится отдельно. Так команда совместила быстрые повседневные расчёты с доступом к миллиардам старых записей.

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

#clickhouse #iceberg
MongoDB → DuckDB: почему способ загрузки имеет значение

Запросы перенесли в DuckDB, но импорт данных стал заметной частью работы. В практическом сравнении автор проверяет три способа загрузки из Java.

На выборке из 485 168 строк с длинными текстовыми полями JDBC executeBatch занял 3 минуты 37 секунд, Appender — 2 минуты 2 секунды, табличная функция — 1 минуту 27 секунд. Время включает последующую сортировку.

В рассмотренной реализации executeBatch выполняет вставки построчно. Appender передаёт настоящие пакеты, а табличная функция позволяет DuckDB самому запрашивать порции данных у Java-кода.

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

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

#duckdb #etl
Как число кандидатов меняет стоимость гибридного поиска

Больше кандидатов для ранжирования означает больше чтений и работы базы. При этом итоговая десятка результатов может измениться совсем немного.

В разборе Lakebase Search приложение Slide Hub объединяет векторный поиск и BM25 через Reciprocal Rank Fusion. Команда сравнила размеры списков кандидатов на 20 запросах.

При сокращении списка с 1000 до 200 число затронутых страниц уменьшилось с 28 972 до 10 401. В итоговом top-10 сохранилось 90,5% результатов относительно варианта с 1000 кандидатами. Это совпадение двух выдач, а не оценка качества по экспертной разметке.

На холодном кеше запрос шёл 387 мс вместо 740 мс; повторный — 11,7 мс вместо 35,3 мс. Эти значения относятся к запросу в базе, а полный путь приложения включает и другие задержки.

Авторы проверяют пределы базы и сервера приложения отдельно. Увеличение ресурсов базы со временем перестало помогать — потребовались дополнительные обработчики запросов приложения.

#поиск #производительность
DuckDB превращает JSON из текстового столбца в типизированные колонки

События часто приходят как JSON в поле payload. Выгружать их в файл, чтобы затем прочитать через read_json, необязательно: команда DuckDB показывает, как выполнить преобразование внутри SQL.

Сначала можно получить общую структуру документов:

SELECT json_group_structure(payload::JSON)
FROM events;


Затем скорректировать типы и передать схему в json_transform. Функция создаст STRUCT, а unnest развернёт его верхний уровень в колонки.

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

Проверьте обработку ошибок: json_transform может заменить значение, которое не удалось преобразовать, на NULL. Для отказа с ошибкой есть json_transform_strict. А вывод схемы по выборке может пропустить редкие поля.

#duckdb #json #etl
iSAM Funds отказалась от части предрасчётов при анализе опционных данных

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

Команда iSAM Funds сначала измерила масштаб задачи, затем организовала параллельную запись в ClickHouse на том же оборудовании, где проверяла решение на PostgreSQL.

В своём эксперименте команда получила сжатие в 35–50 раз относительно прежнего объёма хранения и рост загрузки на одном ядре с 8 тысяч до 800 тысяч строк в секунду. Это результаты конкретного набора данных, схемы и реализации.

Быстрые запросы позволили убрать часть заранее рассчитанных агрегатов и материализованных представлений. Для передачи данных команда использует Apache Arrow.

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

#clickhouse #архитектура #аналитика
Aurora PostgreSQL объединяет данные базы и Iceberg одним запросом

Последние операции лежат в PostgreSQL, многолетняя история — в S3. Для совместного запроса теперь можно обойтись без предварительной загрузки всей истории в операционную базу.

В Aurora PostgreSQL встроили DuckDB: расширение aurora_analytics читает Iceberg и Parquet через внешние таблицы. Дальше их можно объединять с обычными таблицами SQL-запросами.

Движок применяет фильтры и отбор колонок при чтении, а часто используемые данные кеширует. Аналитические запросы можно направлять на читающую реплику.

Нужны Aurora PostgreSQL 17.11+ или 18.6+, расширение и IAM-роль с доступом к данным. Это возможность Aurora, не обычного PostgreSQL.

Отдельной платы за функцию нет, но вычисления Aurora и запросы к S3 оплачиваются. Нагрузку и объём чтения стоит измерить до переноса регулярных отчётов.

#postgresql #iceberg #duckdb
Flink CDC 3.7 проверяет схему существующей таблицы перед записью

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

В Flink CDC 3.7.0 приёмники Paimon и Fluss получили режимы CHECK, TRY_EXPAND и EXPAND. Они позволяют проверять существующую схему и, в зависимости от режима, добавлять или расширять типы неключевых колонок перед записью.

Эта возможность относится именно к указанным приёмникам: переносить её поведение на любой коннектор Flink CDC нельзя.

В релизе также появился Pipeline-коннектор для SQL Server с инкрементальным чтением снимка и синхронизацией изменений схемы.

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

#flink #cdc #dataengineering
Нативный .NET-клиент ClickHouse передаёт данные блоками колонок

ClickHouse обрабатывает данные по колонкам, но при обмене через построчный RowBinary сервер и клиент тратят работу на смену представления.

В новом TCP-клиенте для .NET используется Native-формат: по сети идут блоки колонок. Значения фиксированной длины можно читать пачкой, а не разбирать по одному полю каждой строки.

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

Клиент входит в ClickHouse.Driver, но пока экспериментальный и выдаёт предупреждение CHTCP0001. Поддержка DbConnection для работы через ADO.NET ещё в планах.

Измерять пользу стоит на полном пути данных: чтение блока может ускориться, а последующее создание миллионов объектов останется узким местом приложения.

#clickhouse #dotnet #производительность
DuckDB File Storage Inspection показывает блоки базы и содержимое WAL

Размер файла базы вырос, но из таблиц непонятно, что занимает место? DuckDB File Storage Inspection показывает физическую раскладку: заголовки, метаданные, группы строк, сегменты колонок, свободные и индексные блоки.

Файл подключается в режиме чтения через DuckDB-Wasm и разбирается по блокам. Загружать всю базу в память сразу не требуется.

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

Инструмент помогает изучать повреждённые файлы, но не восстанавливает их. В README указана проверка формата DuckDB 1.5.5; зашифрованные базы не поддерживаются.

Код автора доступен на GitHub. При выборе через браузер передайте файл базы и его WAL вместе, чтобы увидеть обе части.

#duckdb #хранениеданных #диагностика