agentsclimarketplace

Clickhouse migration deep dive

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/clickhouse-pack/skills/clickhouse-migration-deep-dive

Execute ClickHouse schema migrations — ALTER TABLE operations, data migration between engines, versioned migration runners, and zero-downtime schema changes. Use when modifying ClickHouse schemas, migrating data between tables, or implementing versioned migration workflows. Trigger with "clickhouse migration", "clickhouse ALTER TABLE", "clickhouse schema change", "migrate clickhouse", "clickhouse add column", or "clickhouse schema migration".From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill clickhouse-migration-deep-dive

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

5.7 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

ClickHouse Migration Deep Dive

Overview

Plan and execute ClickHouse schema migrations: column changes, engine migrations, ORDER BY modifications, and versioned migration runners. ClickHouse ALTER operations behave unlike PostgreSQL/MySQL — most are asynchronous mutations that rewrite data parts in the background, and some changes (ORDER BY, engine) require full table recreation. This skill walks the safe path for each.

Prerequisites

  • ClickHouse admin access
  • Backup of production data (see clickhouse-prod-checklist)
  • Test environment for validation

Instructions

Follow these steps in order. SQL and runner code for each step live in the linked reference files — keep them open while you work.

Step 1: Classify the operation

Decide whether your change is lightweight (instant, metadata only) or a heavyweight mutation (rewrites parts in the background):

-- Lightweight (instant): ADD COLUMN, RENAME COLUMN, COMMENT COLUMN
ALTER TABLE events ADD COLUMN country LowCardinality(String) DEFAULT '';

-- Heavyweight (mutation): MODIFY COLUMN, DROP COLUMN, DELETE, UPDATE
ALTER TABLE events MODIFY COLUMN properties String CODEC(ZSTD(3));

-- Always monitor mutation progress
SELECT database, table, mutation_id, is_done, parts_to_do
FROM system.mutations WHERE NOT is_done ORDER BY create_time;

Step 2: Run column operations

Use Edit/Write to author the ALTER TABLE statements, then apply them. Add/modify/drop columns, set materialized defaults, and attach codecs. Full DDL semantics and every column-operation variant: DDL & column operations.

Step 3: Recreate the table for ORDER BY / engine changes

ClickHouse has no MODIFY ORDER BY and no in-place engine change. Create a new table, INSERT ... SELECT the data, then atomically RENAME TABLE to swap. Full create → copy → swap → verify → drop recipe for both cases: table recreation.

Step 4: Wire a versioned migration runner

For repeatable, tracked migrations, drive numbered .sql files through a runner that records applied versions in a _migrations table and stops on first failure. Use Write to scaffold runner.ts and the sql/NNN-*.sql files, then run it with npm/node. Full runner, example migration files, and the operation downtime matrix: migration runner.

Output

Applying this skill produces:

  • Executed ALTER statements or recreated-and-swapped tables, with mutations confirmed complete via system.mutations WHERE NOT is_done (empty result).
  • Migration .sql files under migrations/sql/ (e.g. 001-create-events.sql) and a runner.ts that records each applied version in the _migrations table.
  • Verification counts — row counts on the new/old tables matching before the old table is dropped.

Pre-Migration Checklist

  • Backup production data (BACKUP TABLE ... TO S3(...))
  • Test migration on staging with production-like data
  • Check disk space (mutations create temporary extra parts)
  • Schedule during low-traffic window (for heavy mutations)
  • Prepare rollback procedure
  • Verify mutation completes (system.mutations WHERE NOT is_done)

Examples

Add a column (instant, no data rewrite):

ALTER TABLE analytics.events
    ADD COLUMN IF NOT EXISTS country LowCardinality(String) DEFAULT ''
    AFTER user_id;

Change ORDER BY via table recreation and atomic swap:

CREATE TABLE analytics.events_v2 AS analytics.events
ENGINE = MergeTree()
ORDER BY (tenant_id, event_type, toDate(created_at))
PARTITION BY toYYYYMM(created_at);

INSERT INTO analytics.events_v2 SELECT * FROM analytics.events;

RENAME TABLE
    analytics.events TO analytics.events_old,
    analytics.events_v2 TO analytics.events;

More worked examples: column codecs and materialized defaults in column operations, the MergeTree → ReplacingMergeTree engine swap in table recreation, and end-to-end versioned files in migration runner.

Error Handling

ErrorCauseSolution
Cannot ALTER: table has mutationsMutation queue fullWait or cancel: KILL MUTATION WHERE ...
Column already existsRe-running migrationUse IF NOT EXISTS
Cannot convert typeIncompatible type changeCreate new column, backfill, drop old
Not enough disk spaceMutation doubles data temporarilyFree space, then retry

Resources

What ships with it: 3 files

7.4 KB alongside SKILL.md

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.