В мае 2024 года Broadcom заархивировал публичный репозиторий Greenplum: последний коммит остался на месте, дальнейшая разработка ушла в закрытый репозиторий, enterprise-сборка теперь доступна только по подписке. Greenplum как живой OSS-проект остановился — но сам код, выпускавшийся с октября 2015-го, остался под Apache 2.0. Именно на этой кодовой базе стартанули остальные форки.

Те, кто строил аналитику на Greenplum, оказались перед развилкой. Сообщество разделилось: Apache Cloudberry (incubating), Greengage DB от Arenadata, WarehousePG от EDB. Каждый форк продолжает линию, но в собственной траектории. У компании с боевым кластером появляется конкретный вопрос: переехать/остаться в одном из этих форков или мигрировать на принципиально другую платформу и архитектурную парадигму.

Эта статья (сага из трех эпизодов) будет полезна, если у вас уже есть Greenplum-кластер, вы понимаете его DDL/ETL/backup-процессы и хотите оценить, насколько болезненным будет переход на StarRocks.

Также здесь я пытаюсь охватить миграцию с Greenplum на StarRocks как инженерный проект: что меняется в DDL, SQL, ETL и эксплуатации, где миграция почти механическая, а где придется перепроектировать решения. Поэтому статья ближе к техническому сборнику. В этой статье я не пытаюсь покрыть все возможные конфигурации Greenplum в разных компаниях — у каждой за эти 3–5 лет сложился свой путь и архитектура решений на Greenplum, поэтому я опираюсь на общие конструкции.

Привет, Хабр! Меня зовут Александр, я DevRel команды Selena Lakehouse. Пишу про СУБД StarRocks, архитектуры Lakehouse и Streamhouse в Telegram-канале @starrocks_selena (https://t.me/starrocks_selena).

Тут в целом мы стоим перед выбором:

Остаться в семействе (Cloudberry, Greengage, WarehousePG):

Плюсы:

✅ Самый низкозатратный путь по времени и бюджету: DDL и SQL переносятся почти 1:1, PL/pgSQL-логика продолжает работать, команда не учится заново, привычные инструменты (gpbackup, gp_*) остаются на месте.

Минусы:

⚠ Архитектурные ограничения Greenplum переезжают вместе с продуктом: единственный master-узел, неотделимое от вычислений хранилище, операционная нагрузка от VACUUM/ANALYZE, ручное обновление materialized views (в Greenplum 6).

Сменить продукт, оставив MPP-парадигму (ClickHouse, StarRocks)

Плюсы:

✅ Современный движок: векторизация + pipeline-обработка;

✅ Auto-stats и auto-compaction вместо ручного VACUUM/ANALYZE;

✅ Декларативные ускорения: async MV с auto-rewrite (StarRocks) или Projections (ClickHouse) — там, где в Greenplum 6 был manual REFRESH;

✅ Нативная работа с внешними каталогами Iceberg/Delta/Hudi/Paimon/Hive.

Минусы:

⚠ SQL-диалект меняется (MySQL у StarRocks, собственный у ClickHouse; переписываются DDL и SQL-функции), PL/pgSQL-логика мигрирует в UDF (Java/Python в StarRocks, Python в ClickHouse) либо во внешний оркестратор. Multi-statement BEGIN/COMMIT в StarRocks появились с v3.5 (Beta, июнь 2025), расширены в v4.0 — но с ограничениями относительно Greenplum-семантики (детали в A5).

Сменить архитектуру в сторону Lakehouse (Trino + Iceberg или StarRocks в shared-data)

Плюсы:

✅ Разделение хранения и вычислений с независимым масштабированием;

✅ Открытые форматы как Iceberg делают данные переносимыми между движками, единый storage-слой для DWH, ML и ad-hoc-аналитики. Главный выигрыш здесь не в скорости конкретного запроса, а в независимости данных от одного SQL-движка.

Минусы:

⚠ Самая дорогая миграция по человеко-часам: перепроектирование схемы под Iceberg-партиционирование, переписывание ETL-пайплайнов, внедрение catalog-сервиса (Hive Metastore, Polaris), обучение команды новому стеку. Сюда же относится и операционная сложность Iceberg (snapshot management, compaction, orphan files).

Первый путь (остаться в семействе форков) — отдельная тема, требует сравнения Cloudberry / Greengage / WarehousePG между собой, это уже тема коллег, кто плотно с этим занимается. Получается следующая развилка.

Если берем второй путь, оставлять MPP-парадигму, для DWH-сценариев StarRocks к Greenplum ближе, чем ClickHouse, сразу по нескольким архитектурным моментам:

  1. Cascades-оптимизатор отрабатывает многотабличные JOIN-ы по той же логике, что ORCA в Greenplum — с переоценкой порядка по статистикам и broadcast/shuffle-решениями.

  2. Распределение задается явно на уровне DDL (DISTRIBUTED BY HASH(col) BUCKETS N) — у ClickHouse шардирование настраивается серверно.

  3. Репликация работает per-tablet — знакомая концепция после mirror-сегментов.

  4. План в EXPLAIN читается фрагментами с exchange-операторами вместо motion: знакомые приемы отладки перекосов, broadcast/redistribute-решений и колокации переносятся напрямую.

Если же выбран третий путь — менять архитектуру, в таком случае StarRocks и закроет все потребности, в shared-data режиме. Архитектурно это разделение хранения и вычислений: FE (frontend, метаданные) + CN (Compute Nodes, без хранения данных); сегменты с локальными дисками заменяются на объектное хранилище — S3, HDFS или любое S3-совместимое (MinIO, RustFS и т. д.). CN-узлы добавляются и снимаются без ребалансировки данных, потому что данных на них нет — только локальный кэш горячих сегментов. Вычисления масштабируются независимо от хранения. При этом query-движок остается тот же: SQL-диалект, DDL, Cascades-оптимизатор, EXPLAIN, операторы — все, что описано выше про путь 2.

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

Предположим, что решение о миграции уже принято, и даже решено мигрировать на StarRocks. 

Намеренно опускаем: сайзинг StarRocks-кластера, по этой теме будет отдельная большая статья, и различного рода бенчмарков*, сравнение StarRocks с Greengage/ClickHouse.

Этого добра (*) на просторах Habr полно, и некоторые авторы специализируются только на синтетических тестах в своих статьях, но, как показывает практика, все равно заказчик перед покупкой/внедрением делает пилот на своих данных и это рекомендуют все вендоры и интеграторы.

И саму миграцию данных как процесс — экспорт из Greenplum, загрузку в StarRocks (Stream Load / Broker Load / INSERT FROM FILES), валидацию, инкрементальный sync во время параллельной работы. Все это будет в Эпизод II.

11 областей миграции

Прежде чем нырять в детали, посмотрим на картину целиком. Миграция Greenplum → StarRocks это не простое копирование DDL и данных. Обычно всплывают три слоя работ: схема хранения, SQL/процедуры и эксплуатационные процессы, не считая самой миграции данных. Задача разбивается на 11 ключевых областей (может и больше, у каждого свои нюансы), сгруппированных в три блока — от того, что меняется на уровне DDL, до того, что меняется в ежедневной эксплуатации.

Блок A. Хранение и схема — пять областей. Здесь то, что нужно решить и описать в DDL: распределение и параллелизм запросов, формат хранения и компрессия, партиционирование, типы данных и их маппинг, PRIMARY KEY и ACID-семантика.

Блок B. Запросы и семантика — три области. Здесь то, что переписывается на уровне SQL: хранимые процедуры и функции, SQL-диалект и его расхождения, materialized views и индексы.

Блок C. Оперирование и нагрузка — три области. Здесь то, что меняется в эксплуатации: управление нагрузкой через resource groups, бэкап и репликация, VACUUM/ANALYZE и регулярное обслуживание.

Блок А

Любая миграция начинается с DDL: каждый CREATE TABLE в Greenplum нужно перевести на язык StarRocks. Ошибка в DDL потом дорого стоит: можно получить перекос, лишние пересылки, плохую компрессию или неудобный ETL-паттерн. От качества этого перевода зависит все остальное — производительность запросов, поведение ETL, корректность транзакционных гарантий.

Главная разница на уровне DDL — StarRocks требует подумать о том, что в Greenplum было по умолчанию. В DDL Greenplum достаточно описать столбцы и distribution. В StarRocks к этому добавляется выбор табличной модели (Duplicate - по умолчанию / Aggregate / Unique / Primary Key), число бакетов (BUCKETS N или auto-bucketing)  и опциональное объявление колокации.

A1. Распределение (Distribution by)

В Greenplum распределение задается в DDL: DISTRIBUTED BY (col) — hash от столбца определяет, на каком сегменте окажется строка. Есть еще DISTRIBUTED RANDOMLY (равномерно без ключа) и DISTRIBUTED REPLICATED (вся таблица на каждом сегменте — для маленьких справочников).

Когда JOIN идет по distribution-ключу обеих таблиц, пересылок нет — данные уже рядом. Иначе в плане появляется motion-оператор: Broadcast Motion рассылает маленькую таблицу всем сегментам, Redistribute Motion пересылает большую по новому ключу, Gather Motion собирает результат на master. Skew по distribution-ключу — главная операционная проблема.

В StarRocks DDL читается похоже: DISTRIBUTED BY HASH(col) BUCKETS N. Главное отличие —это BUCKETS N: явное число бакетов на партицию (auto-bucketing; с v3.1 для Duplicate Key можно вообще опускать). В Greenplum параллелизм был привязан к числу сегментов; в StarRocks это отдельный механизм — разработчик/DBA сам решает, на сколько бакетов резать таблицу.

Co-located JOIN в StarRocks объявляется явно через Colocation Group. В EXPLAIN вместо motion-операторов будут exchange-операторы — помимо классических Broadcast/Redistribute, StarRocks использует еще Bucket Shuffle и Colocate Exchange.

Условный пример с DDL:

-- Greenplum
CREATE TABLE fact_orders (
    order_id bigint,
    customer_id bigint,
    amount numeric,
    dt date
)
DISTRIBUTED BY (customer_id);

-- StarRocks
CREATE TABLE fact_orders (
    order_id bigint,
    customer_id bigint,
    amount decimal(18,2),
    dt date
)
DUPLICATE KEY(order_id)
PARTITION BY date_trunc('day', dt)
DISTRIBUTED BY HASH(customer_id) BUCKETS 32;

При миграции:

  • Distribution key обычно переносится 1:1

  • Bucket count: документация рекомендует 100 MB–1 GB сжатых данных на tablet (физическое воплощение bucket). Если получилось меньше числа BE-узлов, то надо взять число BE. С v2.5.7 есть auto-bucketing — можно положиться на него вместо ручного расчета.

  • DISTRIBUTED REPLICATED прямого аналога не имеет: для маленьких справочников StarRocks обычно сам выбирает broadcast join (по умолчанию, исходя из размера таблицы), либо можно подсказать через broadcast hint.

A2. Форматы хранения и компрессия

В Greenplum таблицы бывают трех типов хранения. Heap (по умолчанию) — обычный PostgreSQL-формат, под транзакционную нагрузку и UPDATE/DELETE. AO row (append-optimized) — для DWH с массовыми вставками. AO column — колоночное хранение с per-column компрессией (zlib, zstd).

В StarRocks хранение по умолчанию колоночное. Таблицы специализируются под разные сценарии через табличную модель (Duplicate / Aggregate / Unique / Primary Key). Сжатие задается на уровне таблицы: LZ4 (по умолчанию, быстрая запись), ZSTD (выше степень сжатия), ZLIB, SNAPPY.

С версии 3.2.3 в StarRocks есть hybrid row-column storage: данные хранятся одновременно колоночно и построчно — для быстрых point lookup. Фича помечена Preview в документации 4.x, работает только на Primary Key таблицах. Для миграции production ее пока не учитываем. По этой теме у меня на канале также выходил пост.

При миграции:

  • AO column-таблицы переезжают почти прозрачно, так как то же колоночное хранение и похожие кодеки;

  • AO row превращается в Duplicate Key с колоночным форматом;

  • heap с частыми UPDATE/DELETE — отдельный случай: нужна Primary Key модель или пересмотр архитектуры (если таблица была мелкая транзакционная — она может вообще не уехать на DWH-движок).

Компакция в StarRocks автоматическая, без manual VACUUM.

A3. Партиционирование

В Greenplum партиционирование задается при создании таблицы: PARTITION BY RANGE(col) или PARTITION BY LIST(col), с поддержкой multi-level (range внутри range). Для ETL используется ALTER TABLE ... EXCHANGE PARTITION — атомарная замена партиции на заранее подготовленную staging-таблицу.

Один из самых удачных механизмов Greenplum, как мне кажется. Атомарная подмена данных встроена в DDL движка и это задача, для которой в других OLAP-системах приходится собирать собственный паттерн, здесь решается одной командой.

В StarRocks партиционирование тоже задается в DDL: PARTITION BY RANGE(col) или PARTITION BY LIST(col). Дополнительно есть expression-partitioning (PARTITION BY date_trunc('day', dt)) — партиции создаются автоматически при вставке. И есть dynamic partitions для time-partitioning без ручного управления. Очень удобная вещь, я помню на первом месте работы в роли Oracle DBA, и первые мои задачи были ручное создание партиций и субпартиций, занимало много времени подготовить эти скрипты.

При миграции:

  • Range/list переносятся почти один в один;

  • Expression-partitioning может упростить часть DDL: там, в Greenplum делали через cron-jobs или ручные ALTER TABLE ADD PARTITION;

  • Прямого аналога ALTER TABLE EXCHANGE PARTITION в StarRocks нет. ETL-паттерн переписывается на TEMPORARY PARTITION + INSERT OVERWRITE: данные собираются во временную партицию, затем одной командой атомарно подменяется целевая.

Прямого аналога multi-level partitioning (SUBPARTITION) Greenplum в StarRocks нет — у SR partitioning одноуровневый. Аналогичные сценарии закрываются multi-column partitioning (PARTITION BY (col1, col2)) или expression-partitioning, который часто закрывает ту же потребность по time-иерархиям (year/month/day).

A4. Типы данных и их маппинг

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

Скрытый текст
  • NUMERIC/DECIMAL. В Greenplum NUMERIC может быть с произвольной точностью (до 131 072 знаков до запятой). В StarRocks DECIMAL ограничен: DECIMAL128 до P=38 (стандарт), DECIMAL256 до P=76 (с v4.0). Без аргументов DECIMAL берёт дефолт DECIMAL(10, 0) — для большинства DWH-сценариев слишком мало, точность нужно указывать явно (DECIMAL(20,4) и т.п.). Перед миграцией нужно проверить, что значения укладываются в выбранные precision/scale — иначе переполнение.

  • TIMESTAMP WITH TIME ZONE. В Greenplum это отдельный тип с явным учётом таймзоны. В StarRocks DATETIME хранит локальное время, конвертация идёт через session-параметр time_zone.

  • JSONB → JSON. Greenplum хранит JSONB в бинарном формате; StarRocks — в формате JSON, который тоже хранится бинарно (функциональный аналог JSONB, не text JSON: whitespace и порядок ключей не сохраняются). На уровне SQL разница невелика, но синтаксис функций и индексация отличаются.

  • ENUM, composite types, custom types в StarRocks отсутствуют. ENUM мигрирует в VARCHAR с проверкой допустимых значений на уровне ETL-слоя или приложения (CHECK constraints в StarRocks не поддерживаются). Composite types раскладываются на отдельные колонки, JSON-поле или STRUCT (semi-structured тип StarRocks с typed fields). Custom types — отдельная задача переписывания.

A5. PRIMARY KEY и ACID-семантика

В Greenplum транзакционная семантика классическая PostgreSQL: ACID с уровнем изоляции READ COMMITTED, multi-statement транзакции (BEGIN ... COMMIT), ссылочная целостность (PRIMARY KEY, UNIQUE, CHECK работают; FOREIGN KEY. PRIMARY KEY и UNIQUE требуют, чтобы distribution-ключ был подмножеством constraint-столбцов), DDL внутри транзакции. Это позволяет писать ETL в том стиле, к которому привык pgsql-разработчик: начал транзакцию, выполнил несколько операций, закоммитил или откатил.

В StarRocks ACID-семантика устроена иначе. Тип гарантий определяется табличной моделью, которая задается при создании таблицы:

  • Duplicate Key — все строки сохраняются как есть, повторы не убираются. Подходит для логов и event-данных.

  • Aggregate Key — преагрегация на вставке (SUM/MAX/MIN/REPLACE). Подходит для метрик.

  • Unique Key — последняя запись побеждает (last-write-wins). Подходит для CDC-таблиц и slowly changing dimensions.

  • Primary Key — ACID на уровне строки, поддерживает UPDATE/DELETE, оптимизирован под точечные запросы по ключу. Подходит для таблиц с частыми UPDATE/DELETE и нагрузок, где много точечных чтений.

Транзакционная гранулярность исторически была на уровне одной load-операции — каждый INSERT, Stream Load или Broker Load работал как отдельная атомарная транзакция. С v3.5 появилась поддержка multi-statement транзакций со стандартным синтаксисом BEGIN ... COMMIT/ROLLBACK — изначально только для INSERT в одной БД. С v4.0 она расширена до multi-table write-write транзакций (INSERT/UPDATE/DELETE). Для UPDATE/DELETE важно помнить, что в документации написано: поддержка относится к shared-data clusters.

Однако это не полная замена для Greenplum-семантики. Существенные ограничения (проверил на последней версии v4.1.0):

  • SELECT в той же транзакции не видит данные, измененные предыдущими DML (Limited READ COMMITTED).

  • DML на одну таблицу — один тип: после UPDATE/DELETE нельзя сделать INSERT в ту же таблицу в той же транзакции.

  • Только одна БД: cross-database транзакций нет.

  • INSERT OVERWRITE в транзакции запрещен: атомарную подмену партиции придется делать отдельным шагом.

  • Нет DDL внутри транзакции, savepoint, REPEATABLE READ.

Пример поддерживаемой мульти-табличной транзакции
Пример поддерживаемой мульти-табличной транзакции
Пример неподдерживаемой мульти-табличной транзакции
Пример неподдерживаемой мульти-табличной транзакции

При миграции:

  • Выбор табличной модели — основное решение для каждой таблицы. Логи и сырые события в Duplicate Key. Метрики с агрегацией на вставке в Aggregate Key. Dimensions с семантикой последняя запись побеждает (last-write-wins) в Unique Key. Транзакционные таблицы и таблицы под частые UPDATE → Primary Key.

  • Мульти-табличные транзакции в простых случаях (несколько INSERT в одной БД с возможным rollback) теперь покрываются нативно с v3.5. Сложные паттерны все равно переезжают в оркестратор с atomic-цепочками в Airflow / DolphinScheduler / dbt и компенсирующими шагами.

Блок B. Запросы и семантика

Главная разница между Greenplum и StarRocks на этом уровне — в расположении логики. В Greenplum значительную часть бизнес-логики можно реализовать прямо в базе: PL/pgSQL процедуры, тяжелые SQL-запросы с recursive CTE, manual REFRESH MV. В StarRocks движок намеренно «уже» по этим возможностям — часть работы переезжает в ETL-слой (Airflow, DolphinScheduler, dbt), часть — в UDF, а часть автоматизируется самим движком (auto-rewrite MV, auto-stats).

B1. Хранимые процедуры и функции

В Greenplum хранимые процедуры часто значительная часть рабочего кода в боевых системах. PL/pgSQL для основной логики, PL/Python для тяжелой обработки, тысячи строк в проде у крупных команд: ETL-функции с курсорами, аналитические функции с window-операциями, системные хранимки с DML и обработкой ошибок.

В StarRocks CREATE PROCEDURE не поддерживается.

Issue #49439 с запросом на поддержку процедур закрыт без resolution; пользовательских stored procedures нет даже в 4.1. В 4.0 появились системные Iceberg-процедуры (rewrite_data_files, rewrite_manifests, expire_snapshots, remove_orphan_files) через CALL-синтаксис — но это maintenance для Iceberg-таблиц, не пользовательские процедуры. Для пользовательской логики — UDF на Java и Python.

Самое затратное по времени — переписывание ETL-функций в DAG-оркестратор. Здесь нет универсального решения: каждая процедура анализируется отдельно, разбивается на шаги, ставится в зависимости в оркестраторе или модели в dbt. Если в проде Greenplum накоплены тысячи строк PL/pgSQL — этот этап миграции будет самым трудозатратным, и часть логики вообще придется переосмысливать с нуля. Но есть и положительный момент, для команды миграция в эту сторону, кстати, дает архитектурные плюсы.

ETL-логика в Airflow, DolphinScheduler или dbt лежит в Git наравне с продуктовым кодом, проходит code review, тесты, CI/CD — то, что в PL/pgSQL обычно организовывалось отдельно через миграционные скрипты. dbt автоматически строит граф зависимостей моделей и документацию; оркестратор показывает DAG с метриками каждой задачи. Плюс расширяется набор инструментов: в оркестраторе можно подключить любой Python (внешние API, ML-фичи), в dbt — макросы и Jinja-шаблоны.

При миграции хранимая логика разъезжается на три слоя:

  • ETL-оркестратор (Airflow, DolphinScheduler, dbt) — то, что было multi-step ETL-процедурами. Это самый большой кусок: SCD-функции, daily aggregations, snapshot processing.

  • UDF (Java/Python) — точечные функции, которые вызываются из SQL и не зависят от данных в других таблицах. Маппинг 1:1 с PL/pgSQL функциями, возвращающими scalar или table.

  • Materialized views — то, что было MV с manual refresh. В StarRocks MV умеют auto-refresh и auto-rewrite, и часть логики, которая раньше требовала процедуры, описывается декларативно.

B2. SQL dialect

В Greenplum SQL — Postgres-семейство. Полный набор PG-фич: window-функции, recursive CTE, LATERAL JOIN, FILTER в агрегатах, ARRAY_AGG, GENERATE_SERIES, regexp-функции. Идентификаторы трехзвенные: database.schema.table.

В StarRocks SQL — MySQL-семейство. Большинство стандартных конструкций совпадает (window-функции, basic CTE, JOIN-семантика), но есть несколько отличий:

Скрытый текст
  • Иерархия имен. В StarRocks два уровня: database.table для нативных таблиц или catalog.database.table для external catalogs. Schema как промежуточный уровень не используется.

  • LATERAL JOIN — прямого аналога нет. Часть случаев заменяется на CROSS JOIN UNNEST (для array/struct), часть — на pre-flattening в ETL.

  • FILTER (WHERE …) в агрегатах работает (движок переводит в sum_if/count_if внутри). Альтернативно можно писать SUM(CASE WHEN cond THEN col END) для совместимости с другими диалектами.

  • NULL ordering. В Postgres ORDER BY col ставит NULL last, в MySQL и StarRocks — NULL first. Для аналитика, привыкшего к Postgres-семантике, это часто ломает результаты тестов после миграции.

При миграции SQL-запросы проходят через автоматические замены простых случаев (CAST-ы, иерархия имен, datetime-форматы) и ручную правку нюансов (NULL ordering, LATERAL, recursive CTE). Регрессионное тестирование — обязательная часть, потому что многие отличия проявляются только на конкретных данных.

B3. Materialized views и индексы

В Greenplum materialized views — отдельная сущность, обновляются вручную через REFRESH MATERIALIZED VIEW. Поверх таблиц создаются индексы разных типов: btree (по умолчанию), gin (для JSONB и arrays), в GP 7 добавлен brin (для больших таблиц с естественной упорядоченностью), bitmap (для низкокардинальных колонок), expression-индексы (например, по LOWER(email)). DBA подбирает индекс под workload и поддерживает его.

В StarRocks materialized views работают иначе — async или sync, и главное: с автоматическим query rewrite. Это значит, что клиентский SQL не меняется при добавлении MV. Допустим, есть MV с дневной агрегацией продаж, и BI-дашборд делает запрос SELECT customer_id, SUM(amount) ... GROUP BY customer_id к исходной таблице orders. Оптимизатор StarRocks сам распознает, что этот запрос можно посчитать через MV, и подставляет ее в план запроса — пользователь и BI-инструмент про MV не знают. В Greenplum для того же эффекта пришлось бы либо переписать запрос на обращение к MV вручную, либо обернуть всё в view. В StarRocks MV можно добавлять, удалять и пересоздавать, не трогая код дашбордов и приложений.

Индексы в StarRocks устроены иначе:

  • Sort key — основной механизм пропуска данных, задается при создании таблицы. Работает как кластерный индекс: данные физически отсортированы, сканирование по диапазону sort-ключа эффективно.

  • Bloom filter — для high-cardinality колонок, по которым часто идут точечные запросы.

  • Bitmap index — в целом, это тот же класс ускорения фильтров, но переносить GP bitmap indexes механически не стоит: сначала нужно понять, что они закрывали.

  •  Prefix index — автоматический, на основе sort-key.

  • Inverted index (с 3.3) — для full-text search по строковым колонкам.

При миграции:

  1. MV переезжают с упрощением — то, что было manual REFRESH, в StarRocks становится async с auto-rewrite. Часть MV-логики, реализованной в Greenplum через процедуры, в StarRocks описывается одной CREATE MATERIALIZED VIEW.

  2.  Индексы переписываются под другой паттерн. Btree редко нужен — sort key закрывает большинство случаев сканирования. Expression-индексы прямого аналога не имеют, выносятся в обычные колонки или MV. GIN-индексы тоже прямого аналога не имеют: для text search есть inverted index, для других случаев перепроектируется схема.

  3. Стратегия: сначала описать sort key для каждой таблицы под основной запросный паттерн, потом точечно добавить bloom/bitmap по горячим точкам.

Блок C. Оперирование и нагрузка

После DDL и SQL то, что администраторы делают каждый день, чтобы кластер продолжал работать — это управление нагрузкой, бэкапы и репликация, регулярное обслуживание (статистика, очистка, балансировка). Это слой, где у Greenplum-DBA уже сложились свои процессы и инструменты, и при миграции часть из них упрощается, а часть требует пересмотра.

C1. Управление нагрузкой: resource queues / groups

Главная разница на этом уровне — многое из того, что в Greenplum было ручным, в StarRocks делает сам движок. VACUUM, ANALYZE, REFRESH MV отрабатывают автоматически. Resource Groups покрывают тот же набор задач, что и Resource Queues, но настраиваются иначе.

В Greenplum управление нагрузкой работает на двух уровнях. 

Resource Queues — ограничивают конкурентность (ACTIVE_STATEMENTS), приоритеты (PRIORITY), память (MEMORY_LIMIT). Запросы выше лимитов встают в очередь. 

Resource Groups — они дают более тонкий контроль CPU и памяти на уровне процессов, плюс изоляцию OOM.

Подход StarRocks к управлению нагрузкой — шесть взаимодополняющих механизмов (это моя группировка; в документации они описаны раздельно):

  1. Multi-Warehouse (StarRocks Enterprise) — физически отдельные пулы compute-нод: ETL на своих, дашборды на своих. Данные общие, ресурсы раздельные.

  2. Resource Groups — логические лимиты CPU, памяти и concurrency внутри одного пула.

  3. Query Queues — если пороги превышены, запросы встают в очередь, а не роняют систему.

  4. Pipeline DOP — динамически подстраивает параллелизм под текущую нагрузку.

  5. Spill to Disk — тяжелые JOIN / AGG / SORT уходят на диск вместо OOM.

  6. Big Query Kill — автоматически прерывает запросы по лимитам памяти, CPU или scan rows.

C2. Backup и репликация

В Greenplum надежность строится на нескольких механизмах:

  • Mirror-сегменты — каждый primary segment имеет фиксированный mirror на другом узле. Failover автоматический.

  • Standby master — резервная master-нода с журналом, может перехватить роль координатора, failover ручной.

  • gpbackup/gprestore — параллельный backup всего кластера (или отдельных схем/таблиц) с компрессией и шифрованием.

В StarRocks модель надежности построена иначе:

  • Tablet replication — каждый таблет реплицируется N раз (по умолчанию 3). Это N-replica с автоматическим распределением реплик по BE-узлам — модель отличается от fixed-pair mirror в Greenplum. При падении узла остальные реплики продолжают обслуживать запросы; поврежденные таблеты восстанавливаются автоматически.

  • FE high availability — несколько FE-нод в режиме leader/follower через BDBJE-консенсус. При падении leader-FE один из follower-FE поднимается автоматически.

  • Backup в объектное хранилище (для shared-nothing) — BACKUP и RESTORE команды загружают snapshot в S3-совместимое хранилище. Поддерживается резервное копирование per-table или per-database. В shared-data режиме вместо BACKUP/RESTORE используется отдельный механизм Cluster Snapshot.

  • Резервный кластер на случай падения основного — два кластера с асинхронной репликацией по расписанию (например, каждые 15 минут). Одна команда переключает резервный в активный режим: допустимая потеря данных — от 15 минут, восстановление занимает минуты. Резервный кластер доступен на чтение в обычном режиме. Доступно в StarRocks Enterprise (Mirrorship EE с версии 3.3.5) и в Selena Lakehouse.

Главная архитектурная разница: в Greenplum резервирование жестко привязано к парам узлов (primary↔mirror), в StarRocks реплики распределяются по политике, и при добавлении/удалении BE-узлов реплики автоматически перебалансируются (если речь про shared-nothing).

При миграции:

  • Расписание бэкапов переезжает в BACKUP-команды StarRocks с целевым S3-хранилищем;

  • Mirror-сегменты Greenplum концептуально становятся 3-replica tablet'ами в StarRocks (можно настроить и больше реплик для критичных таблиц);

  • Standby master заменяется на multi-FE setup; рекомендуется минимум 3 FE-ноды для отказоустойчивости;

C3. Maintenance: VACUUM, ANALYZE, статистика, compaction

В Greenplum maintenance — регулярный цикл операций, который занимает значимую часть времени DBA:

  • VACUUM для heap-таблиц — освобождает мертвые строки после UPDATE/DELETE. На больших таблицах работает часами, и без него таблицы растут на диске.

  • ANALYZE — пересчет статистики для оптимизатора. Нужен после массовых изменений данных, иначе планы запросов деградируют.

  • VACUUM FULL / REINDEX — на сильно фрагментированных таблицах. Блокирующая операция.

  • gp_toolkit / gp_segment_configuration — мониторинг состояния кластера, ребалансировка.

В StarRocks этот пласт работы сильно сокращен:

  • Compaction (cumulative + base) — автоматическая в фоне. Не нужно ничего запускать руками.

  • Auto-stats — статистика собирается в фоне, оптимизатор всегда видит свежие данные.

  • REFRESH MV — async MV обновляются автоматически по расписанию или event-driven, без ручных действий.

Ручной ANALYZE остается как инструмент для особых случаев: крупная переливка данных, резкое изменение распределения значений, деградация конкретного плана. VACUUM как операции просто нет — место освобождается компактификацией.

Это область, где StarRocks заметно проще в эксплуатации, и это реальный профит, который DBA в будущем получит от такой миграции. Освобождается значительная часть DBA-часов, ранее уходивших на VACUUM-расписания и контроль фрагментации.

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

Главный вывод первой части: миграция Greenplum → StarRocks не выглядит как прыжок в совсем чужую модель. У обоих движков есть MPP-подход, distribution, cost-based optimizer, exchange/motion-логика и привычная для DWH работа с большими таблицами. Но совместимость не полная: самые трудозатратные пункты — табличные модели, процедуры, SQL-диалект и partition exchange.

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

Чтобы не пропустить:

🔹Подписывайтесь на этот блог на Habr

🔹Между статьями цикла — новости StarRocks в Telegram-канале @starrocks_selena (https://t.me/starrocks_selena)