ClickHouse MergeTree Table Generator
A ClickHouse table lives or dies by its sorting key, and the CREATE TABLE syntax packs the engine, partitioning, TTL and codecs into one statement that is easy to get subtly wrong. Describe your columns and this generator writes the DDL, then flags the mistakes that cost you scan performance. It all runs in your browser - nothing is uploaded.
Do more than clickhouse mergetree table generator — meet Chat2DB
Chat2DB is an AI-powered SQL client for Windows, macOS and Linux. Write SQL in natural language, format and optimize queries automatically, and manage MySQL, PostgreSQL, Oracle and 20+ other databases in one workspace.
How to use
- Paste your columns, one 'name Type' pair per line. LowCardinality, Nullable, Decimal and DEFAULT expressions all pass through unchanged.
- Pick a MergeTree engine, set ORDER BY from lowest to highest cardinality, and choose a partition granularity and TTL for the data lifecycle.
- Read the sanity checks for sorting-key and partitioning warnings, then copy the DDL into clickhouse-client or your SQL editor.
Frequently asked questions
How do I choose the ORDER BY key for a ClickHouse table?
Order the columns from lowest to highest cardinality and lead with the columns your queries filter on most. ClickHouse keeps only a sparse primary index - one mark per index_granularity rows, 8192 by default - so a query can skip data only when the WHERE clause matches a prefix of the sorting key. A key of (event_type, user_id, event_time) lets a filter on event_type alone skip most granules, while (user_id, event_time) forces a near-full scan for the same query because user_id is close to unique. Put a timestamp last: it is almost always the highest-cardinality column, and it still gives you good locality within each granule.
What is the difference between PARTITION BY and ORDER BY in ClickHouse?
They solve different problems. PARTITION BY physically splits the table into directories on disk, which makes DROP PARTITION and TTL expiry instant and lets the planner skip entire months; it is a data-lifecycle tool. ORDER BY sorts rows inside each part and drives the sparse index, which is what actually makes queries fast. Beginners often partition by day hoping for speed and end up with thousands of small parts, slow merges and 'too many parts' insert errors. Partition by month (toYYYYMM) unless you genuinely drop data daily, and invest the effort in the sorting key instead.
Does ReplacingMergeTree guarantee my rows are deduplicated?
No, and this trips up nearly everyone. ReplacingMergeTree removes duplicates of the sorting key only when parts are merged, which happens in the background at an unpredictable time - so a SELECT run right after an insert can still return both rows. To get deduplicated results at query time you must either add FINAL to the query, which is correct but costs performance, or aggregate around it with argMax on a version column. Supplying a version column is also what makes the winner deterministic: without one, ClickHouse keeps an arbitrary row from each duplicate group. Chat2DB connects to ClickHouse and shows the merged and unmerged row counts side by side, which makes this easy to reason about: download it at https://chat2db.ai/download or use the web version at https://app.chat2db.ai.
