Changing a table's storage layout (engine or sorting key) in ClickHouse requires a full table rewrite. Doing it in-place can block or slow concurrent reads and writes due to heavy merges and metadata changes, creating real risk for production workloads. Blue/Green avoids this by creating a new versioned table and migrating data live via a materialized view, so traffic continues uninterrupted.
When to use it:
How Moose does it:
version, setting the new orderByFieldsengine (Table modeling).Setting config.version on an OlapTable changes only the underlying table name (suffixes dots with underscores). Your code still refers to the logical table you exported.
Assume the original events table orders by id only. We want to update the
sorting key to optimize reads by ordering on id, createdAt.
import { Key, OlapTable } from "@514labs/moose-lib"; interface EventV0 { id: string; name: string; createdAt: Date;} export const events = new OlapTable<EventV0>("events", { version: "0.0", orderByFields: ["id"] });Create a new table with the same logical name, but set version: "0.1" and update the ordering to id, createdAt. Moose will create events_0_1 in ClickHouse.
import { Key, OlapTable } from "@514labs/moose-lib"; interface EventV1 { id: Key<string>; name: string; createdAt: Date;} export const eventsV1 = new OlapTable<EventV1>("events", { version: "0.1", orderByFields: ["id", "createdAt"] });Create a materialized view that:
events_v0)events_v1)Pass the versioned OlapTable instance as targetTable. If you only pass a tableName, Moose will create an unversioned target.
import { MaterializedView, sql } from "@514labs/moose-lib";import { events } from "../tables/events"; // old tableimport { eventsV1, EventV1 } from "../tables/events_v01"; // new versioned table export const migrateEventsToV01 = new MaterializedView<EventV1>({ materializedViewName: "mv_events_to_0_1", selectTables: [events], selectStatement: sql` SELECT * FROM ${events} `, targetTable: eventsV1,});What happens when you export this view:
INSERT INTO ... SELECT ...)events automatically flow into events_0_1eventsV1).0.1, 1.0, 1.1. Moose will render events_1_1 as the physical name.selectStatement.