The Jerusalem PostThousands of Christians visit West Bank settlements in support after European sanctions, trade bansInquirerPidsog pushes 3 measures to expand maternal care, vaccine accessESPNUSMNT player ratings: Richards scores, steadies backline to get 8/10 in win over ChileESPN DeportesEN VIVO: Cubs rompe No-Hitter a King en la séptimaCNN TürkTÜRKİYE - BELÇİKA MAÇI NE ZAMAN? Milli maç nerede, hangi stadyumda oynanacak? Belçika-Türkiye maçı tarihi, saati ve canlı yayın bilgileri...Capital FMRuto, Dangote Set to Break Ground on Sh2.2tn Lamu Oil Refinery Amid Land DisputeThe Sydney Morning HeraldFremantle councillors lament nasty turn in tree debate as they push ahead with oval plansالشرقبعد موافقة مجلس النواب.. ماذا نعرف عن التعبئة العامة في اليمن؟Il Fatto QuotidianoPerché il centrosinistra fatica a trovare un leader unitario: la spiegazione nella sua ‘natura’SportstarAsian Games 2026 LIVE Updates, Day 12: India mixed, women's archery compound teams win gold, Sunil to contest for bronze in Greco-Roman wrestling; Squash women's team reaches semifinalSouth China Morning PostThere’s been buzz around Carney for a prize long coveted by TrumpCNN بالعربيةبالأسماء.. الوفد المرافق لنائب رئيس الإمارات بزيارة السعودية وتعليق الأمير خالد بن سلمان على اللقاء
The Daily Newsstand · Free, Always
Wednesday, September 30, 2026

Greenplum как расширение PostgreSQL 19

Translate

С 2017 года я слежу за экосистемой вокруг PostgreSQL для выполнения аналитических запросов и использования ее в качестве хранилища данных. И раньше в своей работе использовал AWS Redshift со всем его недостатками и неудобствами для разработчика как форка старой версии PostgreSQL. По моему мнению идеальное решение на основе PostgreSQL должно быть на последней доступной версии СУБД, реализовано в виде расширения, с возможностью запускать для тестов локально в контейнере и позволять использовать существующие расширения последних версий PostGIS / pgvector итп.

Citus казался ближе всех к тому что нужно, но его нельзя считать полноценным Massively Parallel Processing решением, скорее это шардирование данных для OLTP нагрузки.

Greenplum как MPP форк всем хорош и много кто его эксплуатирует в реальных задачах, но версия PostgreSQL, на основе которой он создан, отстает от текущей. Я решил сделать Apache Cloudberry, как самую свежую open source версию Greenplum, в виде расширения для PostgreSQL 19. Пока что это личный эксперимент, а не апстрим релиз Apache Cloudberry. Более 90% кода проекта удалось портировать с помощью LLM и 59% его тестов исходного проекта стало выполняться на его новой версии. У меня на это ушло 12 дней…

Greenplum как MPP форк всегда отставал от актуальной версии PostgreSQL на несколько релизов. Так Greenplum 6 вышел на базе PG 9.4, Greenplum 7 на PG 12, а Apache Cloudberry как продолжателю проекта Greenplum удалось поднять версию PostgreSQL до 16.9 только в мае 2026. И причина здесь в том что эта массивно-параллельная СУБД является форком PostgreSQL: в текущем репозитории было 882 правки исходных текстов PG и добавили еще 646 - это не считая 1.6млн. строк в его оптимизаторе ORCA вместе с тестовыми данными. Переход на каждую новую мажорную версию постгрес - это месяцы слияний исходных текстов. Пока разработчики заканчивают слияние, апстрим успевает уйти от них вперед.

Я же решил срестить ежа с ужом и пойти от обратного - не вливать исходники PostgreSQL в Greenplum, а натянуть Cloudberry поверх PostgreSQL 19 как набор расширений этой СУБД. Но самая главная идея, что даже при небольших модификациях PG 19 для создания новых точек расширения, сервер баз данных с моими патчами ядра без загруженных расширений Cloudberry должен быть неотличим от ванильного PostgreSQL 19 как для пользователя, так и для других расширений и иметь почти неотличимую производительность (максимум доля процента расхождения) от исходного немодифицированного ядра.

Код за меня писал Claude Code в множестве сессий агентами, работающими в параллельных git worktree. Я же обсуждал с LLM первоначальный план разработки расширения, принимал архитектурные решения и проверял его результаты. Даже несмотря на то что я писал серьезно на C/C++ почти 20 лет назад, этот эксперимент я считаю успешным!

На все про ушло 12 дней и 629 коммитов для того чтобы получить MPP движок повторяющий форк Greenplum, а не просто очередной FDW который тащит все данные на координатор. Планы режутся на слайсы, данные при выполнении запросов СУБД пересылаются между сегментами, а транзакции используют распределенные снимки и двухфакторную фиксацию. При этом в самом PostgreSQL потребовалось добавить лишь 22 новых точки расширения (каюсь, первоначально было 28, но потом удалось их уменьшить с некоторыми компромисами).

Почему расширение

Pivotal больше десятилетия назад открыла исходных код Greenplum, но после покупки VMWare компанией Boradcom публичный репозитарий проекта через некоторое время перевели в архив. Тот самый исходных код проекта живет теперь в форках open-gpdb, WarehousePG от EDB и Apache Cloudberry. Последний был основан на Greenplum 7 и попал в инкубатор проектов Apache. PostgreSQL 19 на данный момент еще не стабильная - находится в Beta 4, а релиз кандидат ожидается с недели на неделю.

Расширение дает основное преимущество - использовать последнюю версию СУБД и почти все инструменты экосистемы без их модификация, используя их готовые и собранные. Также упрощается переезд на следующую мажорную версию постгреса, с гораздо меньшими проблемами чем у форка. Чтобы перебазировать исходники нужно лишь перевести 22 небольших патча на 1.5К строк в сумме, а не сливать проекты месяцами.

Для текущих пользователей Greenplum и Cloudberry расширение даст:

  • Актуальный PostgreSQL - от MERGE и последних фишечек SQL/JSON до асинхронного ввода/вывода, параллельный автовакуум

  • Расширения от сообщества - на узлах могут работать апстримные PostGIS 3.7 вместо форка 3.3.2 из Cloudberry, а pgvector доступен 0.8.8. Легко загружаются бинарные модули собранные для ванильного PostgreSQL 19, ведь ABI ядра не изменен.

  • Привычные - DISTRIBUTED BY и классический PARTITION BY … EVERY, gpfdist, gp_toolkit, инструменты gpMgmt от gpinitsystem до gpexpand, а так же вывод EXPLAIN с узлами Motion.

Хотя чудес на все 100% не бывает. За это прийдется заплатить логической миграцией (выгрузка и восстановление), а не выполнение pg_upgrade. 438 параметров конфигурации переименованы с перфиксом gp.*, хотя gpconfig принимает и старые имена. Многое из функционала в DDL под капотом транслируется в теги, шифрование данных на уровне СУБД заменяется пока шифрованием тома в операционной системе.

Новичкам в Greenplum расширение дает:

  • пропатченый PostgreSQL останется с виду самым обычным, если в него не загружено расширение Cloudberry.

  • но даже в одноузловой конфигурации, если загрузить модули расширения, появляются инкрементальные материализованные предствавления, планировщик заданий, таблицы append-optimized и колоночное хранилище PAX, а самое полезное планировщик ORCA.

  • Чтобы использовать MPP в распределенной установки, вам не надо менять привычный PostgreSQL на другую экосистему, на другие драйверы, другие BI-инструменты.

  • Привычные PL/pgSQL, PostGIS и pgvector остаются с вами.

Cloudberry как совместимое с PostgreSQL MPP хранилище данных

Один запрос планирует стоимостный распределенный оптимизатор, план запроса пересылается между узлами в бинарной форме и выполняется он на всех сегментах, при этом они могут перемещать нужные данные между узлами механизмом Motion. Но при этом всем сохраняется ACID транзакции в масштабах всего кластера, становится доступным колоночное хранение данных со сжатием. И над всем этим есть управление рабочей нагрузкой и механизм failover при отказах.

Типичное применение в Data Warehouse на десятки и сотни терабайт в схемах “звезда” и “снежинка”, для отчетов соединяющих множество больших таблиц. Часто применяют как выполнения ELT на SQL и PL/pgSQL.

Если сравнивать с расширениями для PostgreSQL на сентябрь 2026:

Мой порт Cloudberry

Citus 14.2

pg_duckdb 1.1.1

pg_lake 3.5.3

PG-Strom 6.1

Масштаб

кластер сегментов

кластер шардов

один узел

один узел + DuckDB в sidecar-процессе

один сервер с GPU

Выполнение

исполнитель PostgreSQL; слайсы плана на каждом сегменте, Motion между ними

исполнитель PostgreSQL; SQL-фрагменты на каждый шард

векторизованный DuckDB в каждом бэкенде

векторизованный DuckDB в pgduck_server

код для GPU, сгенерированный из SQL

Большие соединения

ORCA, стоимостные распределённые планы

порядок соединений «относительно наивный» (так в его документации); соединения с перераспределением по умолчанию выключены

одна машина

передаются в DuckDB, иначе выполняет PostgreSQL

внутренняя сторона должна помещаться в память GPU

Согласованность

2PC + распределённые снимки

2PC, без глобального снимка

нет транзакций, пишущих и в таблицы PostgreSQL, и в таблицы DuckDB

UPDATE/DELETE в Iceberg выполняются по очереди

как в PostgreSQL

Ядро

22 патча ядра

без изменений

без изменений

без изменений

без изменений

Из всех перечисленных только порт Cloudberry выполняет сложный запрос по большим таблицам как единый распределенный конверный план, в котором каждый узел читает один и тот же распределенный снимок. При этом он позволяет сохранять типы PostGIS/pgvector итп в своих колоночных таблицах и выполнять над ними UPDATE/MERGE операции. На данный момент проигрывает там где важна скорость выполнения на одно процессорное ядро. Executor в PostgreSQL это движок с строчными структурами данных в памяти. В текущем виде это расширение вряд ли легко примут в PostgreSQL как управляемый сервис - ведь ему нужно пропатченное ядро СУБД для выполения, на что не пойдет Azure/AWS.

Если сравнивать с популярными open source решениями используемыми для аналитических запросов, то ClickHouse 26.9 и StarRocks 4.1.5 совсем другие движки с векторизованным колоночным исполнителем запросов. StarRocks имеет свой новый оптимизатор Cascades и lakehouse каталоги, а транзакции из нескольких операций у него пока в бета версии. У ClickHouse свой диалект и эксперементальные транзакции.

Разрыв в исполнителях показывает ClickBench: одна плоская таблица на 100 млн строк, 43 запроса, без соединений, машина c6a.4xlarge. Каждое значение — сумма по 43 запросам времени «горячего» прогона, то есть лучшего из прогонов 2 и 3, как его определяет ClickBench; заголовок каждого столбца ведёт на опубликованный файл результатов:

ClickHouse

DuckDB

StarRocks

pg_duckdb (Parquet)

Cloudberry 1.5.3 (AOCO)

Greenplum 7.1 (AOCO)

Citus columnar

PostgreSQL heap

17,6 с

26,3 с

44,5 с

52,5 с

294,7 с

768,6 с

1745,1 с

11875,4 с

Исходные данные: репозиторий ClickBench на коммите ad5c59b (2026-09-28); те же результаты в виде графиков — на benchmark.clickhouse.com.

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

Поэтому мое эмпирическое правило…

  • Cloudberry - для сложного SQL по большим таблицам с транзакциями, PL/pgSQL, PostGIS и pgvector на собственных серверах;

  • Citus - для мультитенантных нагрузок с маршрутизацией по ключу;

  • pg_duckdb и pg_lake - для скорости на одном узле и данных в Iceberg;

  • ClickHouse - отлично подходит для логов и событий;

  • StarRocks - для джоинов таблиц, в сочетании с эластичностью lakehouse.

Правила разработки

Начал все с создания плана. Написал Fable5 “изучи каталог проекта cloudberry и разберись, как с помощью хуков и макросов перенести его на PostgreSQL v19 с минимальными изменениями кода” и “спланируй процесс переноса функционала так, чтобы изменения в ядре PostgreSQL не меняли ни работу, ни функциональность сервера PostgreSQL при незагруженном расширении Greenplum”. В результате получил семь правил, которым кодинг агенты строго следовали:

  • используй в первую очередь существующие точки расширения в PG: хуки, табличные методы доступа, CustomScan, менеджер ресурсов WAL, фоновые процессы, security label, FDW;

  • Где их не хватает, добавь свой минимальный хук. Собственный hook здесь - это указатель на функцию по умолчанию равный NULL, экспортируемая функция, список регистрации или выключенный по-умолчанию флаг. Существующие сигнатуры не должны меняться, ни одна структура внутри PostgreSQL не должна переименовываться, не меняются форматы каталога, WAL и страниц, ни протокол;

  • Без загруженного расширения сервер должен вести себя как ванильный;

  • Существующий код Cloudberry не правится. Весь порт - новый каталог pg19/, а файлы апстрим проекта не редактируются, что должно упростить слияния. Если же файл нужно менять, то переноситься копией в директорию расширения с объяснением что модифицированно.

  • ORCA за planner_hook, а не перед ним: применяются переписывания SQL запросов вместо патчей внутри оптимизатора;

  • Сторонние расширения остаются из апстрим, без правок. Если нужна адаптация, то она выполняется в pg19/, как было сделано для пары фич PostGIS;

Ванильность ядра проверяется в тестах сравнением запусков двух docker образов, собранных из одного и того же PostgreSQL с серией патчей и без нее:

  • собственный meson test PostgreSQL: проходят те же 371 тест;

  • abidiff: 32 символа добавлено, 0 изменено;

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

  • идентификаторы запросов: совпадают;

  • каталоги данных и потоковая репликация: взаимозаменяемы в обе стороны;

  • cachegrind: от −0,005% до +0,155% инструкций при пороге 0,5% (проверка);

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

  • модуль-зонд устанавливает каждый хук и проверяет его действие.

В этих проверках был смысл и первый же тест нового хука combo-CID уронил сервер.

Там где существующих хуков не хватало, пришлось добавить 22 новых

На полностью немодифицированном ядре СУБД Greenplum мог бы работать скорее как другой продукт: сегменты бы получали SQL в виде текста вместо подготовленных планов, у каждого бы были свои OID и снимки, как реализовано в Citus. MPP executor нужно чтобы весь кластер разделял один план и одну и ту же транзакцию. Точек расширения в PostgreSQL 19 для этого нет и поэтому пришлось “колхозить” новые патчи для ядра.

Потребность

Патчи

Почему не подходит ни один существующий хук

Одинаковые OID на всех узлах

R1 new_oid_hook

у выделения OID нет хука

Все слайсы одновременно, читатели видят незафиксированные строки писателя

R2 хуки combo-CID, R4 XactAdoptTransactionState()

транзакцию разделяют только параллельные рабочие процессы самого PostgreSQL

2PC в порядке Cloudberry; табличные блокировки без взаимоблокировок при повышении

O33, O30

XACT_EVENT_COMMIT срабатывает, когда транзакция уже видима; режимы блокировок первым выбирает парсер

Синтаксис Cloudberry, gp_segment_id, SELECT *, скрывающий счётчики матпредставлений

O26, O10, O31, O28

хука парсера нет; системные столбцы меняют каталоги

Распределённый ANALYZE, инкрементальные матпредставления

O3, O27

выборка строк из heap жёстко зашита; режим обслуживания статичен

Хранилища append-optimized и PAX, diskquota, контрольные суммы

O13–O18, O21, O23

TableAmRoutine не расширить, не сломав ABI; у менеджера хранения нет хуков

Табличные пространства на каждом узле, защита памяти, тесты сбоев

O32, O25, O29

в redo зашиты фиксированные пути; методы контекстов памяти объявлены static const

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

Из новых патчей четыре хука достаточно универсальны чтобы их предлагать в апстрим PG: реестр табличных AM, события файлов smgr, хук парсера запросов и хук OID.

Изменения же форматов и протокола так просто не перенести ни через один собственный хук:

  • нестандартные сообщения libpq;

  • 20 общих для кластера каталогов;

  • 81 ключевое слово;

  • 217 фиксированных OID;

  • TDE на уровне кластера.

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

Архитектура

Снаружи это Greenplum координатор, который хранит каталог и планирует запросы, а сегменты - каждый полноценный экземпляр PostgreSQL 19 со своей порцией строк данных на другом хосте. Новое лишь то, как это все связано между собой в реализации.

Разбор SQL реализован без форка граматики (как сделано в Cloudberry). Модуль gp_sql разбивает каждый оператор на токены собственным сканером PG и заменяет синтаксис Greenplum стандартным для СУБД, а дальше через ProcessUtility_hook получает доступ к параметрам, которые без него PostgreSQL отверг бы и выдал ошибку:

CREATE TABLE sales (id bigint, dt date)
DISTRIBUTED BY (id)
PARTITION BY RANGE (dt)
  (START (date '2026-01-01') END (date '2027-01-01')
   EVERY (interval '1 month'));

-- до грамматики PostgreSQL 19 доходит как (упрощённо):
CREATE TABLE sales (id bigint, dt date)
PARTITION BY RANGE (dt)
WITH (gp.distributed_by = '(id)',
      gp.partition_by = $gp$PARTITION BY RANGE (dt) (START ...)$gp$);

Одни оператор после разбора остается одним оператором. Ранняя версия порта, выдававшая два на выходе, ломала все драйвера которые используют prepared statement. Но при этом при ошибках позиция ее внутри запроса сохраняется на позицию в непереписанного текста. Граматика форка это одно из мест которые в форке приходилось мерджить, с конфликтами, при каждом новом релизе.

ORCA же написан так (четыре его библиотеки ядра), что не включают ни одного заголовочного файла из PostgreSQL, поэтому ее 920 файлов компилируются из дерева исходников Cloudberry без единой модификации. Связь с ядром СУБД через транслятор порта Query ↔ DXL ↔ план (27 файлов, ~33 тыс. строк) и через слой врапперов. Из 198 функций слоя враппера 170 потребовали только правки “#include”, сильный дрейф API относительно старой версии PostgreSQL обнаружен только в шести местах враппера. Что ORCA не “переваривает” приходится переписывать в запросе перед. Как например любой пространственный предикат PostGIS потребовал перезаписи запроса перед ORCA.

Нестандартные сообщения протокола Cloudberry оборвали бы сеанс PostgreSQL 19, поэтому диспетчер это обычный клиент libpg с SCRAM или TLS, который отправляет каждый слайс внутри SELECT gp_internal.exec_fragment(...), а planner_hook на сегменте подставляет вместо запроса этот фрагмент плана.

Распределенный снимок приходит в виде SET LOCAL. На каждом сегменте процесс-писатель выполняет один слайс, а процессы-читатели остальные: они устанавливают транзакцию от писателя через новый хук ядра R4, вступают в его группу блокировок и разрешают комбинированные идентификаторы команд combo CID используя хук R2. Остальное это стандартный механизм рабочих процессов PostgreSQL.

Motion передают строки потоком по TCP / по UDP Cloudberry с управлением потоком, по UDP2 или через прокси-мультиплексор всех Motion между двумя узлами.

Компоненты

Модуль

Роль

Как подключается

gp_core

файл кластера, диспетчер, Motion, интерконнект, DDL на каждом узле, 2PC, распределённые снимки, детектор взаимоблокировок, FTS, gp_toolkit

хуки исполнителя, утилитных команд и планировщика; фоновые процессы; пользовательский rmgr для WAL; метки безопасности; CustomScan; R1, R2, R4, O3, O10, O29-O33

gp_orca

ORCA, транслятор, счётчики откатов, переписывания до ORCA

planner_hook, CustomScan, хуки EXPLAIN

gp_sql

синтаксис Cloudberry, теги, таблицы-директории, скрипты расширений на каждом узле

O26, ProcessUtility_hook, rmgr для WAL

gp_ao, pax

строковые и колоночные таблицы append-optimized, PAX, bitmap-индекс

табличные AM, O13–O18, O21, O23, rmgr для WAL

gp_exttable, pxf_fdw, gpcloud, datalake_fdw

внешние данные: file, gpfdist, http, s3, PXF, Iceberg

FDW, табличные AM

gp_resource, gp_security, gp_matview, gp_task, diskquota

группы ресурсов на cgroups, защита памяти, профили, инкрементальные матпредставления, планировщик заданий, квоты

метки, O25, O27, O28, O21, фоновые процессы

gpfts, gpMgmt

переключение координатора при отказе; инструменты управления Cloudberry

программы, работающие через SQL и собственные initdb, pg_ctl, pg_basebackup, pg_rewind из PostgreSQL 19

Что видит администратор:

  • gp_core загружается первым, а модули, рассчитанные только на предзагрузку, отказываются выполнять LOAD, так что сервер никогда не работает наполовину инициализированным.

  • Собственных общих каталогов у порта нет. Атрибуты ролей хранятся в общих метках безопасности, секреты - в служебной базе данных, а топология - в файле кластера. gp_segment_configuration и подобные ему объекты - представления.

Ограничения

  • Унаследованные от PostgreSQL 19

    • имена параметров расширений должны содержать точку, отсюда gp.*;

    • теги команд - фиксированный список;

    • CHECK_FOR_INTERRUPTS() не принимает колбэков, поэтому выполняющийся запрос переходит в другую группу ресурсов, только пока он чего-то ждёт;

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

  • Порт в сравнении с Cloudberry:

    • MPP-вариант планировщика PostgreSQL из Cloudberry, «Route B», не портирован, поэтому то, от чего отказывается ORCA, идёт более медленным маршрутом;

    • на коротких запросах планирование в ORCA обходится дороже: 13,7 мс против 0,25 мс для точечного поиска одной строки, по замерам проекта pgorca;

    • параллелизм внутри сегмента распространяется только на слайс писателя;

    • SERIALIZABLE на кластере - это REPEATABLE READ, как и в Greenplum.

  • Особенности MPP:

    • координатор - единственный планировщик и точка входа;

    • соединения не по ключу распределения гоняют данные по сети;

    • ограничения уникальности должны включать ключ распределения;

    • добавление узлов означает перераспределение данных.

Процесс разработки

17 сентября шесть агентов-исследователей изучили каждый свою область кода Cloudberry. Скрипт проверил все 1 440 их ссылок вида file:lines, и в тот же день в диалоге с LLM были приняты 14 решений по реализации.

Вопросы по реализации агенты решали сами и записывали, почему решили так. Всё, что касалось ядра PostgreSQL, общей ветки или удаления, приходило ко мне. Крупные этапы разработки делились между параллельными агентами, у каждого своя ветка и свой worktree: M8 строили девять агентов, ещё семь вычищали ошибки и пропущенные тесты.

Веха

Даты

Результат

M0 каркас

18 сент.

все модули собираются и загружаются; проверки ванильности проходят

M1 один узел

18–22 сент.

SQL Cloudberry, ORCA, PostGIS; 239 регрессионных тестов PostgreSQL строка в строку

M2 кластер

22–24 сент.

диспетчер, Motion, потоковый интерконнект

M3 транзакции

23–24 сент.

2PC, распределённые снимки, детектор взаимоблокировок

M4–M6

24–26 сент.

зеркала и FTS; AO, PAX, внешние таблицы; группы ресурсов

M7 паритет и инструменты

26–27 сент.

gpMgmt поверх инструментов PostgreSQL 19, PostGIS на кластере, замеры TPC

M8

27–28 сент.

UDP2, прокси, gpfts, gpexpand, четыре дополнительных расширения

Коммитов по дням: 10, 9, 15, 26, 31, 29, 87, 51, 87, 186 и 98. Первые дни ушли на ORCA и её транслятор, где понимание что там происходит было важнее скорости, закладывался фундамент. С 24 сентября, когда появилась реализация кластера и параллельный запуск тестов, этапы пошли внахлёст.

Несколько сюрпризов было в процессе:

  • Ноль сегментов: Одноузловой режим поначалу сообщал о нуле сегментов. Отладочная сборка ORCA молча отдавала каждый запрос запасному планировщику. Релизная сборка делила на ноль и обрезала бесконечность до 1e+250, по случайности выдавая правдоподобные планы.

  • Бит 0x0400: Cloudberry решает, звать ли ORCA, по флагу курсора 0x0400, который в PostgreSQL 19 означает CURSOR_OPT_CUSTOM_PLAN. Дословный перенос скомпилировался бы без единой ошибки и выключил бы ORCA для каждого специализированного плана.

  • Повышение блокировок: Когда табличная блокировка Cloudberry бралась после более слабой блокировки парсера, в pgbench “сыпались” 87% параллельных UPDATE. Поэтому и появился патч ядра O30.

  • Мой рабочий стол в linux закрывался: Сорок три параллельных тестовых задания исчерпали 60 ГБ ОЗУ, и OOM killer прихватил вместе с ними сеанс рабочего стола. Теперь раннер запускает задание, только если заявленная для него память помещается в свободную.

Нефункциональные требования и ORCA на TPC

Измерялись такие требования: ванильное поведение, накладные расходы хуков, стабильность ABI, воспроизводимость сборок и правильность ответов. Все цифры получены на Docker-образах, собранных из закоммиченных веток. Полный прогон тестовых наборов порта - это 58 - 64 задания, и он укладывается в 500 - 900 секунд.

Решающий замер касался Cloudberry MPP planner (Route B). Моё указание было таким: сначала устранить ошибки ORCA, вызванные самим портом, а затем, прежде чем решать, измерить реальную нагрузку.

Начальные условия:

  • 22 запроса TPC-H и 99 запросов TPC-DS в том виде, в каком они в DuckDB;

  • один координатор и четыре сегмента в одном контейнере на 16-ядерном хосте с 60 ГБ памяти;

  • без assert-проверок, данные в tmpfs, JIT и параллельные запросы выключены;

  • эталон — ответы DuckDB, сверка с точностью до цента.

TPC-H

TPC-DS

Спланировано ORCA

22/22

99/99

Ответы совпадают с DuckDB

все

все

ORCA VS маршрута сбора, среднее геометрическое

3,1× (4,4 с против 123 с, 20 запросов)

4,0× (25 с против 386 с, 96 запросов)

Не завершились за 120 с на маршруте сбора

q17, q20

04, 14, 64

Исходные данные:

  • Стенд для бенчмарка - pg19/test/tpc в порте: он генерирует данные, загружает кластер, прогоняет каждый запрос под ORCA и маршрутом сбора и сравнивает строки.

  • Запросы и эталонные ответы взяты из наборов DuckDB 1.5.5: TPC-H - запросы и ответы для SF1, TPC-DS - запросы и ответы для SF1.

  • Записанный прогон стенда - в сообщении коммита beaf7379d12: 121 из 121, 3,13× и 3,94×, и те же пять незавершённых запросов.

Итоги в таблице взяты из первого, трёхраундового замера

Под ORCA эти пять запросов выполняются за 0,2 - 1,6 с, а все 121 запрос - за 34 с. На шести коротких запросах (0,1 - 0,75 с) ORCA медленнее более чем на пятую часть. На регрессионном наборе Cloudberry собственные причины fallback плана в порте сократились с 563 до 52; остался унаследованный список из ORCA, в котором нестандартные collation. Агент предлагает сфокусироваться на уменьшении fallback от ORCA к планировщику PG, а не портировать 30–45 тыс. строк Route B. Свое же решение по портированию Cloudberry MPP планировщика я пока не принял, но план его реализации уже подготовил.

В результате

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

  • ядро PostgreSQL с 22 моими хуками и доказуемо ванильное по поведению и совместимости без загруженного Greenplum расширения;

  • немодифицированные исходники Cloudberry и ORCA.

  • работают немодифицированные PostGIS и pgvector, должны работать и другие расширения, для поиска ближайших соседей в pgvector даже удалось сделать оптимизации в планировщике для проброса ORDER BY … LIMIT … на сегменты;

  • более 90% кода СУБД портировано в виде расширений: 93% (или 97% если не учитывать Cloudberry MPP планировщик - Route B в моем плане), а 380тыс строк ORCA переиспользуются с помощью обертки в коде расширения.

Пока запускаются 691 из 1180 тестовых файлов Cloudberry - нужно увеличивать это покрытие. Также в планах на реализацию остаток isolation2 и greenplum_schedule. Возможно перенесу и Cloudberry MPP как fallback для ORCA.

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

Исследование кода сдабривалось ссылками на фрагменты кода, созданием прототипов и измерениями их метрик. Инварианты при кодировании и рефакторинге проверялись тестами, выполнено - значит что разработанный функционал проходит тесты исходной системы. А если есть расхождения, то они точно так же ссылаются на факты о текущем состоянии разработки в этой фазе. И пониманием в какой фазе в будущем этот тест пройдет в его немодифицированном варианте. Тесты запускались параллельно в docker контейнерах максимально используя доступные 32 потока и 64Гб ОЗУ, чтобы ускорить итерации разработки.

Запущенные агенты в последних этапах работали параллельно в изолированных worktree, каждый серьезный шаг по какому пути продолжать разработку или варианты решений при отклонениях в архитектуре проекта я брал на себя. Форку Greenplum понадобились годы чтобы перейти с ядра 9.4 на 12, в случае же с расширением это редактирование 22 небольших патчей ядра PostgreSQL и связанного с ним кода расширения.

Все еще используете старые версии PostgreSQL? “Тогда мы идем к вам!”

Результат проекта: серия патчей ядра, порт, инструкция по сборке.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.