ClickHouse Best Practices
Guidance for ClickHouse covering schema design, query optimization, and data ingestion. Contains 28 atomic rules across 3 categories (schema, query, insert), prioritized by impact. Extended with 15 reference files covering cluster management, backups, monitoring, and integrations.
Official docs: ClickHouse Best Practices
⚠️ Security Considerations
Credential Placeholders
Example credentials in documentation (password123, AKIAIOSFODNN7EXAMPLE) are placeholders only. Never use these in production. Use proper secret management:
- Environment variables
- Secret managers (AWS Secrets Manager, HashiCorp Vault, etc.)
- Kubernetes secrets (for K8s deployments)
- ClickHouse named collections with external configuration
Installation & Operations
For installation and operational procedures:
- Follow official documentation links provided in reference files
- Prefer package managers (
apt, yum, helm) over direct downloads
- Use versioned artifacts instead of
latest in production
- Test procedures in non-production environments first
IMPORTANT: How to Apply This Skill
Before answering ClickHouse questions, follow this priority order:
- Check for applicable rules in the
rules/ directory
- If rules exist: Apply them and cite them in your response using "Per
rule-name..."
- If no rule exists: Check
references/ for deeper topic coverage
- If neither covers it: Use general ClickHouse knowledge or search documentation
- Always cite your source: rule name, reference file, or URL
Why rules take priority: ClickHouse has specific behaviors (columnar storage, sparse indexes, merge tree mechanics) where general database intuition can be misleading. The rules encode validated, ClickHouse-specific guidance.
Review Procedures
For Schema Reviews (CREATE TABLE, ALTER TABLE)
Read these rule files in order:
rules/schema-pk-plan-before-creation.md — ORDER BY is immutable
rules/schema-pk-cardinality-order.md — Column ordering in keys
rules/schema-pk-prioritize-filters.md — Filter column inclusion
rules/schema-pk-filter-on-orderby.md — Query filter alignment
rules/schema-types-native-types.md — Proper type selection
rules/schema-types-minimize-bitwidth.md — Numeric type sizing
rules/schema-types-lowcardinality.md — LowCardinality usage
rules/schema-types-avoid-nullable.md — Nullable vs DEFAULT
rules/schema-types-enum.md — Enum for finite value sets
rules/schema-partition-low-cardinality.md — Partition count limits
rules/schema-partition-lifecycle.md — Partitioning purpose
rules/schema-partition-query-tradeoffs.md — Partition pruning trade-offs
rules/schema-partition-start-without.md — Start without partitioning
rules/schema-json-when-to-use.md — JSON type usage
Check for:
For Query Reviews (SELECT, JOIN, aggregations)
Read these rule files:
rules/query-join-choose-algorithm.md — Algorithm selection
rules/query-join-use-any.md — ANY vs regular JOIN
rules/query-join-filter-before.md — Pre-join filtering
rules/query-join-consider-alternatives.md — Dictionaries/denormalization
rules/query-join-null-handling.md — join_use_nulls setting
rules/query-index-skipping-indices.md — Secondary index usage
rules/query-mv-incremental.md — Incremental materialized views
rules/query-mv-refreshable.md — Refreshable materialized views
Check for:
For Insert Strategy Reviews (data ingestion, updates, deletes)
Read these rule files:
rules/insert-batch-size.md — Batch sizing requirements
rules/insert-async-small-batches.md — Async insert usage
rules/insert-format-native.md — Native format for performance
rules/insert-mutation-avoid-update.md — UPDATE alternatives
rules/insert-mutation-avoid-delete.md — DELETE alternatives
rules/insert-optimize-avoid-final.md — OPTIMIZE TABLE risks
Check for:
Output Format
Structure review responses as follows:
## Rules Checked
- `rule-name-1` — Compliant / Violation found
- `rule-name-2` — Compliant / Violation found
...
## Findings
### Violations
- **`rule-name`**: Description of the issue
- Current: [what the code does]
- Required: [what it should do]
- Fix: [specific correction]
### Compliant
- `rule-name`: Brief note on why it's correct
## Recommendations
[Prioritized list of changes, citing rules]
Rule Categories by Priority
| Priority |
Category |
Impact |
Prefix |
Count |
| 1 |
Primary Key Selection |
CRITICAL |
schema-pk- |
4 |
| 2 |
Data Type Selection |
CRITICAL |
schema-types- |
5 |
| 3 |
JOIN Optimization |
CRITICAL |
query-join- |
5 |
| 4 |
Insert Batching |
CRITICAL |
insert-batch- |
1 |
| 5 |
Mutation Avoidance |
CRITICAL |
insert-mutation- |
2 |
| 6 |
Partitioning Strategy |
HIGH |
schema-partition- |
4 |
| 7 |
Skipping Indices |
HIGH |
query-index- |
1 |
| 8 |
Materialized Views |
HIGH |
query-mv- |
2 |
| 9 |
Async Inserts |
HIGH |
insert-async- |
2 |
| 10 |
OPTIMIZE Avoidance |
HIGH |
insert-optimize- |
1 |
| 11 |
JSON Usage |
MEDIUM |
schema-json- |
1 |
Quick Reference
Schema Design — Primary Key (CRITICAL)
schema-pk-plan-before-creation — Plan ORDER BY before table creation (immutable)
schema-pk-cardinality-order — Order columns low-to-high cardinality
schema-pk-prioritize-filters — Include frequently filtered columns
schema-pk-filter-on-orderby — Query filters must use ORDER BY prefix
Schema Design — Data Types (CRITICAL)
schema-types-native-types — Use native types, not String for everything
schema-types-minimize-bitwidth — Use smallest numeric type that fits
schema-types-lowcardinality — LowCardinality for <10K unique strings
schema-types-enum — Enum for finite value sets with validation
schema-types-avoid-nullable — Avoid Nullable; use DEFAULT instead
Schema Design — Partitioning (HIGH)
schema-partition-low-cardinality — Keep partition count 100-1,000
schema-partition-lifecycle — Use partitioning for data lifecycle, not queries
schema-partition-query-tradeoffs — Understand partition pruning trade-offs
schema-partition-start-without — Consider starting without partitioning
Schema Design — JSON (MEDIUM)
schema-json-when-to-use — JSON for dynamic schemas; typed columns for known
Query Optimization — JOINs (CRITICAL)
query-join-choose-algorithm — Select algorithm based on table sizes
query-join-use-any — ANY JOIN when only one match needed
query-join-filter-before — Filter tables before joining
query-join-consider-alternatives — Dictionaries/denormalization vs JOIN
query-join-null-handling — join_use_nulls=0 for default values
Query Optimization — Indices (HIGH)
query-index-skipping-indices — Skipping indices for non-ORDER BY filters
Query Optimization — Materialized Views (HIGH)
query-mv-incremental — Incremental MVs for real-time aggregations
query-mv-refreshable — Refreshable MVs for complex joins
Insert Strategy — Batching (CRITICAL)
insert-batch-size — Batch 10K-100K rows per INSERT
Insert Strategy — Async (HIGH)
insert-async-small-batches — Async inserts for high-frequency small batches
insert-format-native — Native format for best performance
Insert Strategy — Mutations (CRITICAL)
insert-mutation-avoid-update — ReplacingMergeTree instead of ALTER UPDATE
insert-mutation-avoid-delete — Lightweight DELETE or DROP PARTITION
Insert Strategy — Optimization (HIGH)
insert-optimize-avoid-final — Let background merges work
Quick Decision Guides
Which Table Engine?
Need to store data?
├── < 1M rows, dimension → Memory
└── ≥ 1M rows → MergeTree family
├── Deduplication? → ReplacingMergeTree(version)
├── Changelog? → CollapsingMergeTree(sign)
├── Pre-aggregation? → AggregatingMergeTree()
├── Replication? → ReplicatedMergeTree(...)
└── Default → MergeTree()
See references/table-engines.md for complete reference.
Common Issues & Quick Fixes
| Issue |
Quick Fix |
| Too many parts |
OPTIMIZE TABLE table FINAL (see insert-optimize-avoid-final) |
| Slow query |
EXPLAIN SELECT ... to check index usage |
| Mutation stuck |
Check system.mutations, consider alternatives per insert-mutation-avoid-update |
| Replication lag |
Check system.replication_queue, ZooKeeper |
| OOM on query |
Increase max_memory_usage, optimize query |
See references/debugging.md for detailed troubleshooting.
Deep Reference Files
For topics beyond the 28 rules, see the references/ directory:
Schema & Table Design
references/core-concepts.md — Architecture, data model, internals
references/schema-design.md — Database engines, migrations, version control
references/table-design.md — ORDER BY, partitioning, column selection
references/table-engines.md — Complete MergeTree family reference
Query & Performance
references/sql-reference.md — Complete SQL dialect, data types
references/query-optimization.md — EXPLAIN, JOINs, projections, skip indexes
references/advanced-features.md — Materialized views, mutations, TTL, dictionaries
Operations & Cluster
references/debugging.md — Query debugging, merges, mutations, replication
references/cluster-management.md — Distributed tables, replication, sharding
references/backup-restore.md — Backup strategies, disaster recovery
references/monitoring.md — Query monitoring, health checks, system queries
Integration & Best Practices
references/integrations.md — Kafka, S3, PostgreSQL, MySQL, BI tools
references/best-practices.md — Complete checklist and anti-patterns
references/external.md — Altinity KB links, official docs
references/system-queries.md — Ready-to-use queries for operations
Version: 1.4.0
Rules: Synced with ClickHouse/agent-skills (Apache-2.0)
References: Altinity Knowledge Base (200+ articles) + ClickHouse Official Docs
1---2name: clickhouse3description: MUST USE when reviewing ClickHouse schemas, queries, or configurations. Contains 28 rules that MUST be checked before providing recommendations. Always read relevant rule files and cite specific rules in responses.4---5
6# ClickHouse Best Practices
7
8Guidance for ClickHouse covering schema design, query optimization, and data ingestion. Contains 28 atomic rules across 3 categories (schema, query, insert), prioritized by impact. Extended with 15 reference files covering cluster management, backups, monitoring, and integrations.
9
10> **Official docs:** [ClickHouse Best Practices](https://clickhouse.com/docs/best-practices)
11
12---
13
14## ⚠️ Security Considerations
15
16### Credential Placeholders
17Example credentials in documentation (`password123`, `AKIAIOSFODNN7EXAMPLE`) are placeholders only. Never use these in production. Use proper secret management:
18- Environment variables
19- Secret managers (AWS Secrets Manager, HashiCorp Vault, etc.)
20- Kubernetes secrets (for K8s deployments)
21- ClickHouse named collections with external configuration
22
23### Installation & Operations
24For installation and operational procedures:
25- Follow official documentation links provided in reference files
26- Prefer package managers (`apt`, `yum`, `helm`) over direct downloads
27- Use versioned artifacts instead of `latest` in production
28- Test procedures in non-production environments first
29
30---
31
32## IMPORTANT: How to Apply This Skill
33
34**Before answering ClickHouse questions, follow this priority order:**
35
361. **Check for applicable rules** in the `rules/` directory
372. **If rules exist:** Apply them and cite them in your response using "Per `rule-name`..."
383. **If no rule exists:** Check `references/` for deeper topic coverage
394. **If neither covers it:** Use general ClickHouse knowledge or search documentation
405. **Always cite your source:** rule name, reference file, or URL
41
42**Why rules take priority:** ClickHouse has specific behaviors (columnar storage, sparse indexes, merge tree mechanics) where general database intuition can be misleading. The rules encode validated, ClickHouse-specific guidance.
43
44---
45
46## Review Procedures
47
48### For Schema Reviews (CREATE TABLE, ALTER TABLE)
49
50**Read these rule files in order:**
51
521. `rules/schema-pk-plan-before-creation.md` — ORDER BY is immutable
532. `rules/schema-pk-cardinality-order.md` — Column ordering in keys
543. `rules/schema-pk-prioritize-filters.md` — Filter column inclusion
554. `rules/schema-pk-filter-on-orderby.md` — Query filter alignment
565. `rules/schema-types-native-types.md` — Proper type selection
576. `rules/schema-types-minimize-bitwidth.md` — Numeric type sizing
587. `rules/schema-types-lowcardinality.md` — LowCardinality usage
598. `rules/schema-types-avoid-nullable.md` — Nullable vs DEFAULT
609. `rules/schema-types-enum.md` — Enum for finite value sets
6110. `rules/schema-partition-low-cardinality.md` — Partition count limits
6211. `rules/schema-partition-lifecycle.md` — Partitioning purpose
6312. `rules/schema-partition-query-tradeoffs.md` — Partition pruning trade-offs
6413. `rules/schema-partition-start-without.md` — Start without partitioning
6514. `rules/schema-json-when-to-use.md` — JSON type usage
66
67**Check for:**
68- [ ] PRIMARY KEY / ORDER BY column order (low-to-high cardinality)
69- [ ] Data types match actual data ranges
70- [ ] LowCardinality applied to appropriate string columns
71- [ ] Partition key cardinality bounded (100-1,000 values)
72- [ ] ReplacingMergeTree has version column if used
73
74### For Query Reviews (SELECT, JOIN, aggregations)
75
76**Read these rule files:**
77
781. `rules/query-join-choose-algorithm.md` — Algorithm selection
792. `rules/query-join-use-any.md` — ANY vs regular JOIN
803. `rules/query-join-filter-before.md` — Pre-join filtering
814. `rules/query-join-consider-alternatives.md` — Dictionaries/denormalization
825. `rules/query-join-null-handling.md` — join_use_nulls setting
836. `rules/query-index-skipping-indices.md` — Secondary index usage
847. `rules/query-mv-incremental.md` — Incremental materialized views
858. `rules/query-mv-refreshable.md` — Refreshable materialized views
86
87**Check for:**
88- [ ] Filters use ORDER BY prefix columns
89- [ ] JOINs filter tables before joining (not after)
90- [ ] Correct JOIN algorithm for table sizes
91- [ ] Skipping indices for non-ORDER BY filter columns
92
93### For Insert Strategy Reviews (data ingestion, updates, deletes)
94
95**Read these rule files:**
96
971. `rules/insert-batch-size.md` — Batch sizing requirements
982. `rules/insert-async-small-batches.md` — Async insert usage
993. `rules/insert-format-native.md` — Native format for performance
1004. `rules/insert-mutation-avoid-update.md` — UPDATE alternatives
1015. `rules/insert-mutation-avoid-delete.md` — DELETE alternatives
1026. `rules/insert-optimize-avoid-final.md` — OPTIMIZE TABLE risks
103
104**Check for:**
105- [ ] Batch size 10K-100K rows per INSERT
106- [ ] No ALTER TABLE UPDATE for frequent changes
107- [ ] ReplacingMergeTree or CollapsingMergeTree for update patterns
108- [ ] Async inserts enabled for high-frequency small batches
109
110---
111
112## Output Format
113
114Structure review responses as follows:
115
116```
117## Rules Checked
118- `rule-name-1` — Compliant / Violation found
119- `rule-name-2` — Compliant / Violation found
120...
121
122## Findings
123
124### Violations
125- **`rule-name`**: Description of the issue
126 - Current: [what the code does]
127 - Required: [what it should do]
128 - Fix: [specific correction]
129
130### Compliant
131- `rule-name`: Brief note on why it's correct
132
133## Recommendations
134[Prioritized list of changes, citing rules]
135```
136
137---
138
139## Rule Categories by Priority
140
141| Priority | Category | Impact | Prefix | Count |
142|----------|----------|--------|--------|-------|
143| 1 | Primary Key Selection | CRITICAL | `schema-pk-` | 4 |
144| 2 | Data Type Selection | CRITICAL | `schema-types-` | 5 |
145| 3 | JOIN Optimization | CRITICAL | `query-join-` | 5 |
146| 4 | Insert Batching | CRITICAL | `insert-batch-` | 1 |
147| 5 | Mutation Avoidance | CRITICAL | `insert-mutation-` | 2 |
148| 6 | Partitioning Strategy | HIGH | `schema-partition-` | 4 |
149| 7 | Skipping Indices | HIGH | `query-index-` | 1 |
150| 8 | Materialized Views | HIGH | `query-mv-` | 2 |
151| 9 | Async Inserts | HIGH | `insert-async-` | 2 |
152| 10 | OPTIMIZE Avoidance | HIGH | `insert-optimize-` | 1 |
153| 11 | JSON Usage | MEDIUM | `schema-json-` | 1 |
154
155---
156
157## Quick Reference
158
159### Schema Design — Primary Key (CRITICAL)
160
161- `schema-pk-plan-before-creation` — Plan ORDER BY before table creation (immutable)
162- `schema-pk-cardinality-order` — Order columns low-to-high cardinality
163- `schema-pk-prioritize-filters` — Include frequently filtered columns
164- `schema-pk-filter-on-orderby` — Query filters must use ORDER BY prefix
165
166### Schema Design — Data Types (CRITICAL)
167
168- `schema-types-native-types` — Use native types, not String for everything
169- `schema-types-minimize-bitwidth` — Use smallest numeric type that fits
170- `schema-types-lowcardinality` — LowCardinality for <10K unique strings
171- `schema-types-enum` — Enum for finite value sets with validation
172- `schema-types-avoid-nullable` — Avoid Nullable; use DEFAULT instead
173
174### Schema Design — Partitioning (HIGH)
175
176- `schema-partition-low-cardinality` — Keep partition count 100-1,000
177- `schema-partition-lifecycle` — Use partitioning for data lifecycle, not queries
178- `schema-partition-query-tradeoffs` — Understand partition pruning trade-offs
179- `schema-partition-start-without` — Consider starting without partitioning
180
181### Schema Design — JSON (MEDIUM)
182
183- `schema-json-when-to-use` — JSON for dynamic schemas; typed columns for known
184
185### Query Optimization — JOINs (CRITICAL)
186
187- `query-join-choose-algorithm` — Select algorithm based on table sizes
188- `query-join-use-any` — ANY JOIN when only one match needed
189- `query-join-filter-before` — Filter tables before joining
190- `query-join-consider-alternatives` — Dictionaries/denormalization vs JOIN
191- `query-join-null-handling` — join_use_nulls=0 for default values
192
193### Query Optimization — Indices (HIGH)
194
195- `query-index-skipping-indices` — Skipping indices for non-ORDER BY filters
196
197### Query Optimization — Materialized Views (HIGH)
198
199- `query-mv-incremental` — Incremental MVs for real-time aggregations
200- `query-mv-refreshable` — Refreshable MVs for complex joins
201
202### Insert Strategy — Batching (CRITICAL)
203
204- `insert-batch-size` — Batch 10K-100K rows per INSERT
205
206### Insert Strategy — Async (HIGH)
207
208- `insert-async-small-batches` — Async inserts for high-frequency small batches
209- `insert-format-native` — Native format for best performance
210
211### Insert Strategy — Mutations (CRITICAL)
212
213- `insert-mutation-avoid-update` — ReplacingMergeTree instead of ALTER UPDATE
214- `insert-mutation-avoid-delete` — Lightweight DELETE or DROP PARTITION
215
216### Insert Strategy — Optimization (HIGH)
217
218- `insert-optimize-avoid-final` — Let background merges work
219
220---
221
222## Quick Decision Guides
223
224### Which Table Engine?
225
226```
227Need to store data?
228├── < 1M rows, dimension → Memory
229└── ≥ 1M rows → MergeTree family
230 ├── Deduplication? → ReplacingMergeTree(version)
231 ├── Changelog? → CollapsingMergeTree(sign)
232 ├── Pre-aggregation? → AggregatingMergeTree()
233 ├── Replication? → ReplicatedMergeTree(...)
234 └── Default → MergeTree()
235```
236
237See `references/table-engines.md` for complete reference.
238
239### Common Issues & Quick Fixes
240
241| Issue | Quick Fix |
242|-------|-----------|
243| Too many parts | `OPTIMIZE TABLE table FINAL` (see `insert-optimize-avoid-final`) |
244| Slow query | `EXPLAIN SELECT ...` to check index usage |
245| Mutation stuck | Check `system.mutations`, consider alternatives per `insert-mutation-avoid-update` |
246| Replication lag | Check `system.replication_queue`, ZooKeeper |
247| OOM on query | Increase `max_memory_usage`, optimize query |
248
249See `references/debugging.md` for detailed troubleshooting.
250
251---
252
253## Deep Reference Files
254
255For topics beyond the 28 rules, see the `references/` directory:
256
257### Schema & Table Design
258- `references/core-concepts.md` — Architecture, data model, internals
259- `references/schema-design.md` — Database engines, migrations, version control
260- `references/table-design.md` — ORDER BY, partitioning, column selection
261- `references/table-engines.md` — Complete MergeTree family reference
262
263### Query & Performance
264- `references/sql-reference.md` — Complete SQL dialect, data types
265- `references/query-optimization.md` — EXPLAIN, JOINs, projections, skip indexes
266- `references/advanced-features.md` — Materialized views, mutations, TTL, dictionaries
267
268### Operations & Cluster
269- `references/debugging.md` — Query debugging, merges, mutations, replication
270- `references/cluster-management.md` — Distributed tables, replication, sharding
271- `references/backup-restore.md` — Backup strategies, disaster recovery
272- `references/monitoring.md` — Query monitoring, health checks, system queries
273
274### Integration & Best Practices
275- `references/integrations.md` — Kafka, S3, PostgreSQL, MySQL, BI tools
276- `references/best-practices.md` — Complete checklist and anti-patterns
277- `references/external.md` — Altinity KB links, official docs
278- `references/system-queries.md` — Ready-to-use queries for operations
279
280---
281
282**Version**: 1.4.0
283**Rules**: Synced with [ClickHouse/agent-skills](https://github.com/ClickHouse/agent-skills) (Apache-2.0)
284**References**: Altinity Knowledge Base (200+ articles) + ClickHouse Official Docs