Как Delivery Hero сократила задержку обработки рекламных событий
В рекламном пайплайне Delivery Hero средний промежуток между событием и его записью сократился с 61 минуты до 1,2 секунды. Команда перешла с часовых пакетов на Apache Flink.
Пайплайн расшифровывает события, удаляет дубликаты и асинхронно обогащает их данными из DynamoDB. Затем многодневное соединение связывает взаимодействия с заказами, а агрегаты сохраняются в отчётную базу каждые пять минут.
Дедупликация держит ключи в RocksDB-состоянии 30 часов. Инкрементальные checkpoints уходят в S3; после сбоя повторно доставленные события отсеиваются. Так команда получила фактически однократный биллинг поверх доставки at-least-once.
Эксплуатационные расходы снизились примерно на 57%. Задержка 1,2 секунды относится к записи событий, а не к обновлению отчётных агрегатов.
Архитектура обработки и результаты миграции
В рекламном пайплайне Delivery Hero средний промежуток между событием и его записью сократился с 61 минуты до 1,2 секунды. Команда перешла с часовых пакетов на Apache Flink.
Пайплайн расшифровывает события, удаляет дубликаты и асинхронно обогащает их данными из DynamoDB. Затем многодневное соединение связывает взаимодействия с заказами, а агрегаты сохраняются в отчётную базу каждые пять минут.
Дедупликация держит ключи в RocksDB-состоянии 30 часов. Инкрементальные checkpoints уходят в S3; после сбоя повторно доставленные события отсеиваются. Так команда получила фактически однократный биллинг поверх доставки at-least-once.
Эксплуатационные расходы снизились примерно на 57%. Задержка 1,2 секунды относится к записи событий, а не к обновлению отчётных агрегатов.
Архитектура обработки и результаты миграции
Как анализировать IP-адреса и подсети встроенными SQL-функциями
В сетевых журналах IP выглядит как строка, но проверка попадания в подсеть требует работы с диапазонами. Разбор адресов регулярками и собственные UDF усложняют такие запросы на больших объёмах.
В Databricks Runtime 18 LTS и новее доступны встроенные функции для IPv4, IPv6 и CIDR. Они принимают строковое и бинарное представления адресов.
Функция ip_cidr_contains(cidr, needle) проверяет, входит ли адрес или другая подсеть в заданный блок. Её можно использовать для соединения журналов соединений со справочником опасных сетей.
В статье таким запросом обогащают сетевые события и ищут источники, сканирующие много адресов и портов. Операции встроены в движок, поэтому оптимизатор и Photon могут ускорять их выполнение.
Пример SQL для анализа сетевых журналов
В сетевых журналах IP выглядит как строка, но проверка попадания в подсеть требует работы с диапазонами. Разбор адресов регулярками и собственные UDF усложняют такие запросы на больших объёмах.
В Databricks Runtime 18 LTS и новее доступны встроенные функции для IPv4, IPv6 и CIDR. Они принимают строковое и бинарное представления адресов.
Функция ip_cidr_contains(cidr, needle) проверяет, входит ли адрес или другая подсеть в заданный блок. Её можно использовать для соединения журналов соединений со справочником опасных сетей.
В статье таким запросом обогащают сетевые события и ищут источники, сканирующие много адресов и портов. Операции встроены в движок, поэтому оптимизатор и Photon могут ускорять их выполнение.
Пример SQL для анализа сетевых журналов
Как ускорить GROUP BY по повторяющимся строкам в DuckDB
В наборе железнодорожных данных 380 959 строк, но всего 537 названий станций. При группировке по названию движок снова и снова хеширует и сравнивает одни и те же строки.
Команда DuckDB предлагает вынести названия в таблицу измерений, а в основной таблице хранить числовые ключи. Для 537 значений достаточно двухбайтового
Числовые ключи уменьшают размер записей хеш-таблицы и стоимость сравнения. При компактном диапазоне ключей оптимизатор может выбрать агрегацию с прямой индексацией массива.
В разборе с SQL-примерами показаны создание справочника и его обновление. Приём полезен для повторных запросов по длинным строкам с частыми повторами. Он не уменьшает число групп; для почти уникальных значений выгода ограничена.
В наборе железнодорожных данных 380 959 строк, но всего 537 названий станций. При группировке по названию движок снова и снова хеширует и сравнивает одни и те же строки.
Команда DuckDB предлагает вынести названия в таблицу измерений, а в основной таблице хранить числовые ключи. Для 537 значений достаточно двухбайтового
USMALLINT. Запрос сначала агрегирует по ключам, затем возвращает названия через JOIN уже небольшого результата. Для top-N соединение можно выполнить после LIMIT.Числовые ключи уменьшают размер записей хеш-таблицы и стоимость сравнения. При компактном диапазоне ключей оптимизатор может выбрать агрегацию с прямой индексацией массива.
В разборе с SQL-примерами показаны создание справочника и его обновление. Приём полезен для повторных запросов по длинным строкам с частыми повторами. Он не уменьшает число групп; для почти уникальных значений выгода ограничена.
Как сократить паузы при ребалансировке Kafka
Добавление потребителя в большую группу может задержать обработку событий: участникам нужно перераспределить партиции. Протокол KIP-848 переносит координацию на брокер и выполняет перераспределение инкрементально. Потребители с неизменившимися назначениями продолжают работу.
В Amazon MSK нужен Kafka 4.0+ и клиент с поддержкой протокола. На клиенте задают
Новый протокол не отменяет диагностику задержек. Проверьте фактически используемый протокол по логам, стабильность потребителей и корректное завершение через
В инструкции AWS разобраны переход на KIP-848 и проверка результата по consumer lag. Материал пригодится для потоковых пайплайнов с частыми перезапусками и масштабированием обработчиков.
Добавление потребителя в большую группу может задержать обработку событий: участникам нужно перераспределить партиции. Протокол KIP-848 переносит координацию на брокер и выполняет перераспределение инкрементально. Потребители с неизменившимися назначениями продолжают работу.
В Amazon MSK нужен Kafka 4.0+ и клиент с поддержкой протокола. На клиенте задают
group.protocol=consumer. Интервал heartbeat, таймаут сессии и алгоритмы назначения теперь управляются на стороне брокера; прежние клиентские параметры нужно убрать.Новый протокол не отменяет диагностику задержек. Проверьте фактически используемый протокол по логам, стабильность потребителей и корректное завершение через
consumer.close().В инструкции AWS разобраны переход на KIP-848 и проверка результата по consumer lag. Материал пригодится для потоковых пайплайнов с частыми перезапусками и масштабированием обработчиков.
Как выполнять свой код рядом с данными в ClickHouse
Чтобы посчитать токены в сохранённых запросах к LLM, обычно выгружают тексты, вызывают библиотеку и загружают результат обратно. Executable UDF позволяет вызвать такой код из SQL внутри ClickHouse Cloud.
В разборе рабочего примера Rust-функция считает токены при вставке данных через материализованное представление. Отдельная Python-функция с сетевым доступом периодически отправляет выборку ответов на оценку модели.
Функции используют CPU и память того же сервиса, что и запросы. Их расходы видны в
В тесте подсчёта токенов Rust оказался в 1,4 раза быстрее Python. Это результат конкретных библиотек и нагрузки: сама смена языка ускорения не гарантирует. Сетевой доступ пока доступен Python-функциям; Native runtime предназначен для вычислений.
Чтобы посчитать токены в сохранённых запросах к LLM, обычно выгружают тексты, вызывают библиотеку и загружают результат обратно. Executable UDF позволяет вызвать такой код из SQL внутри ClickHouse Cloud.
В разборе рабочего примера Rust-функция считает токены при вставке данных через материализованное представление. Отдельная Python-функция с сетевым доступом периодически отправляет выборку ответов на оценку модели.
Функции используют CPU и память того же сервиса, что и запросы. Их расходы видны в
system.query_log: время выполнения, ожидание пула и объём переданных данных. Версии можно закреплять отдельно для каждого сервиса.В тесте подсчёта токенов Rust оказался в 1,4 раза быстрее Python. Это результат конкретных библиотек и нагрузки: сама смена языка ускорения не гарантирует. Сетевой доступ пока доступен Python-функциям; Native runtime предназначен для вычислений.
Как менять таблицу Iceberg без переписывания старых файлов
Таблица выросла, диапазона числового поля больше не хватает, а запросы требуют другого партиционирования. В Iceberg такие изменения можно выполнить через метаданные.
В практическом разборе Redshift показаны добавление, удаление и переименование колонок, безопасное расширение типов и изменение полей партиционирования через
При смене партиционирования новые данные записываются по обновлённой схеме, а старые файлы сохраняют прежнюю раскладку. Движок учитывает оба варианта при чтении. Для замены одного преобразования другим предусмотрена атомарная операция
Изменение метаданных не перераспределяет уже записанные данные. Схему стоит выбирать под реальные фильтры и соединения; если нужно изменить физическую раскладку старых файлов, потребуется отдельная переработка данных.
Таблица выросла, диапазона числового поля больше не хватает, а запросы требуют другого партиционирования. В Iceberg такие изменения можно выполнить через метаданные.
В практическом разборе Redshift показаны добавление, удаление и переименование колонок, безопасное расширение типов и изменение полей партиционирования через
ALTER TABLE. Колонки отслеживаются по уникальным идентификаторам. Для добавленного поля старые строки возвращают NULL.При смене партиционирования новые данные записываются по обновлённой схеме, а старые файлы сохраняют прежнюю раскладку. Движок учитывает оба варианта при чтении. Для замены одного преобразования другим предусмотрена атомарная операция
REPLACE PARTITION FIELD.Изменение метаданных не перераспределяет уже записанные данные. Схему стоит выбирать под реальные фильтры и соединения; если нужно изменить физическую раскладку старых файлов, потребуется отдельная переработка данных.
❤1
Как поделиться Parquet через небольшой каталог DuckDB
Чтобы дать коллегам доступ к набору Parquet-файлов, можно подготовить DuckDB-файл только с представлениями. Он хранит запросы и имена отношений, а сами данные остаются в объектном хранилище.
В руководстве команды DuckDB создают VIEW над удалённым файлом и публикуют каталог по URL. Получатель подключает его в режиме READ_ONLY и обращается к представлениям как к таблицам.
В определениях VIEW можно закрепить названия колонок, фильтры и соединения. Если данные разделили на файлы по годам или переименовали поле, автор обновляет представление, сохраняя привычный запрос для потребителей.
Каталог не заменяет доступ к источникам: читателю нужны права и на DuckDB-файл, и на данные, на которые он ссылается. Для изменения опубликованного каталога редактируют локальную копию и загружают её заново. Скорость запросов зависит от сети и устройства Parquet-файлов.
#duckdb #dataengineering
Чтобы дать коллегам доступ к набору 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 #производительность
У клиента ClickHouse простой SELECT после простоя соединения занимал около 64 мс вместо 32 мс. Команда обнаружила дополнительный сетевой обмен, хотя вычисление запроса было быстрым.
В Native-протоколе клиент ждёт пакет EndOfStream. Перед ним сервер отправляет результат и служебные пакеты с логами, прогрессом и метриками. После простоя TCP уменьшает окно перегрузки: в него может не поместиться вся эта последовательность.
С TCP_NODELAY небольшие записи уходят сразу и создают много отдельных TCP-сегментов. Сервер исчерпывает окно и ждёт подтверждения клиента, прежде чем отправить остаток. Так появляется лишний RTT.
В разборе расследования проблему воспроизводят через Linux network namespaces. Исправление — собрать служебные пакеты в буфер и отправлять вместе. Число 32 мс относится к сети конкретного клиента; причина полезна для диагностики хвоста задержек после простоя.
#clickhouse #производительность
Как изменить партиции Spark Streaming и сохранить состояние
Число партиций stateful-запроса закрепляется в checkpoint. Поэтому изменение
В разборе Databricks показана функция On-Demand State Repartitioning. Она доступна в Public Preview для Databricks Runtime 18+ с RocksDB state store.
Процедура требует остановки запроса: задайте новое значение
Длительность операции видна в
#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-таблицу
В демо события поступления, перевода и выписки превращают в историю и текущую занятость коек. Funke отвечает за разбор и загрузку; смысл полей и правила расчёта показателей по-прежнему определяют специалисты предметной области.
#pyspark #dataengineering
Медицинские системы обмениваются 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
Запрос читает слишком много файлов, а таблица постепенно замедляется? Причину можно искать в метаданных Iceberg, открывая их через DuckDB.
В разборе команды DuckDB показан путь от каталога до строк. Каталог хранит указатель на актуальный JSON-файл метаданных. Тот ведёт к списку манифестов и самим манифестам в Avro, а дальше — к файлам данных и удалений.
Каждое изменение создаёт новые файлы и переключает указатель каталога. Старые версии остаются, пока их не очистит процедура обслуживания.
В манифестах можно проверить границы значений колонок и партиции: соответствуют ли они фильтру запроса и позволяют ли исключить ненужные файлы. Число манифестов и файлов удалений помогает оценить последствия частых небольших изменений.
В статье есть SQL для обхода этих слоёв. Сводные счётчики снимков стоит использовать как подсказку: спецификация делает их необязательными, и другой движок может их не заполнить.
#iceberg #duckdb
Polars 2.0: потоковое выполнение стало стандартным
В Polars 2.0 вызов
В описании релиза команда отдельно предупреждает о порядке строк: для JOIN, GROUP BY и ряда других операций он по умолчанию не гарантируется. Если порядок нужен, его следует запросить через
Включена и начальная поддержка выгрузки промежуточных данных на диск. Она работает для сортировок, оконных функций и многих выражений. Такая поддержка для JOIN и GROUP BY на момент релиза ещё в планах.
По умолчанию выгрузка начинается примерно при 80% занятой RAM, бюджет диска — 64 ГБ. Обновление поэтому стоит проверять на своих тяжёлых запросах: сравнить память, место для временных файлов и порядок строк в результате. Больший объём данных ещё не означает, что любая цепочка операций сможет завершиться на ограниченной памяти.
#polars #dataengineering
В Polars 2.0 вызов
collect() у LazyFrame по умолчанию использует потоковый движок. Это меняет и расход памяти, и некоторые свойства результата.В описании релиза команда отдельно предупреждает о порядке строк: для JOIN, GROUP BY и ряда других операций он по умолчанию не гарантируется. Если порядок нужен, его следует запросить через
maintain_order=True там, где параметр поддерживается.Включена и начальная поддержка выгрузки промежуточных данных на диск. Она работает для сортировок, оконных функций и многих выражений. Такая поддержка для JOIN и GROUP BY на момент релиза ещё в планах.
По умолчанию выгрузка начинается примерно при 80% занятой RAM, бюджет диска — 64 ГБ. Обновление поэтому стоит проверять на своих тяжёлых запросах: сравнить память, место для временных файлов и порядок строк в результате. Больший объём данных ещё не означает, что любая цепочка операций сможет завершиться на ограниченной памяти.
#polars #dataengineering
Почему DISTINCT недостаточно для дедупликации во Flink
В бесконечном потоке нужно решить не только, какие события считать одинаковыми, но и сколько времени помнить уже встреченные ключи. Без ограничения состояния оно будет расти вместе с числом уникальных событий.
В разборе Дэвида Андерсона варианты Flink SQL сравниваются по расходу состояния, задержке, обработке поздних событий и типу выходного потока. DISTINCT может выдавать обновления, что ограничивает его использование дальше в пайплайне.
Есть и ловушка настройки: подсказка
Для узкой задачи «оставить первое событие по ключу» автор показывает ProcessTableFunction с состоянием и TTL. После истечения срока тот же ключ снова может пройти. Поэтому время хранения должно следовать из допустимого интервала повторной доставки, а не только из доступной памяти.
#flink #streaming
В бесконечном потоке нужно решить не только, какие события считать одинаковыми, но и сколько времени помнить уже встреченные ключи. Без ограничения состояния оно будет расти вместе с числом уникальных событий.
В разборе Дэвида Андерсона варианты 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 #качество_данных
Журналы разных систем описывают одних пользователей и действия разными полями. Аналитикам приходится согласовывать эти различия при каждом расследовании.
В кейсе 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
Параллельное чтение в 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
Отчёту может понадобиться несколько лет операций или вся история портфеля за десятилетия. Хранить оба набора в одном быстром слое оказалось необязательно.
В разборе архитектуры 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
Запросы перенесли в 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 мс. Эти значения относятся к запросу в базе, а полный путь приложения включает и другие задержки.
Авторы проверяют пределы базы и сервера приложения отдельно. Увеличение ресурсов базы со временем перестало помогать — потребовались дополнительные обработчики запросов приложения.
#поиск #производительность
Больше кандидатов для ранжирования означает больше чтений и работы базы. При этом итоговая десятка результатов может измениться совсем немного.
В разборе 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.
Сначала можно получить общую структуру документов:
Затем скорректировать типы и передать схему в json_transform. Функция создаст STRUCT, а unnest развернёт его верхний уровень в колонки.
Если сохранить результат отдельной таблицей, следующие запросы будут работать с обычными типизированными колонками без повторного разбора JSON.
Проверьте обработку ошибок: json_transform может заменить значение, которое не удалось преобразовать, на NULL. Для отказа с ошибкой есть json_transform_strict. А вывод схемы по выборке может пропустить редкие поля.
#duckdb #json #etl
События часто приходят как 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 #архитектура #аналитика
У одного базового инструмента могут быть тысячи связанных опционов. Поэтому число исходных инструментов плохо описывает реальную нагрузку на хранение и аналитику.
Команда 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
Последние операции лежат в PostgreSQL, многолетняя история — в S3. Для совместного запроса теперь можно обойтись без предварительной загрузки всей истории в операционную базу.
В Aurora PostgreSQL встроили DuckDB: расширение aurora_analytics читает Iceberg и Parquet через внешние таблицы. Дальше их можно объединять с обычными таблицами SQL-запросами.
Движок применяет фильтры и отбор колонок при чтении, а часто используемые данные кеширует. Аналитические запросы можно направлять на читающую реплику.
Нужны Aurora PostgreSQL 17.11+ или 18.6+, расширение и IAM-роль с доступом к данным. Это возможность Aurora, не обычного PostgreSQL.
Отдельной платы за функцию нет, но вычисления Aurora и запросы к S3 оплачиваются. Нагрузку и объём чтения стоит измерить до переноса регулярных отчётов.
#postgresql #iceberg #duckdb