← Previous: Module 2 - Table Engines 🏠 Home Next: Module 4 - Replication β†’

πŸ”€ MODULE 3

Sharding Strategy & Distribution
Duration: 6-8 hours | Week 3
πŸ“š What is Sharding & Distribution?

Sharding in a Nutshell

Sharding is the process of distributing data across multiple nodes in a cluster. Each node (shard) holds a portion of the data, allowing ClickHouse to scale horizontally and handle datasets too large for a single server. The Distributed engine lets you query data across all shards transparently, as if it were a single table.

πŸ“Š

Horizontal Scaling

Scale to petabytes by adding more nodes. Each shard processes its portion of data independently.

⚑

Parallel Processing

Queries execute in parallel across all shards, dramatically reducing response time for large datasets.

πŸ”„

Data Distribution

Sharding keys determine how data is split. Smart key selection ensures balanced distribution.

πŸ›‘οΈ

Fault Tolerance

Combined with replication, sharding provides resilience. Loss of one shard doesn't stop the cluster.

Single Node vs Distributed Architecture

Single Node

  • All data on one server
  • Limited by disk space and memory
  • Queries process on one machine
  • No fault tolerance
  • Simple to setup and manage
  • Good for: < 10TB data

Distributed Cluster

  • Data spread across multiple nodes
  • Scales to petabytes
  • Queries parallelized across nodes
  • Can survive node failures
  • More complex setup
  • Good for: 100TB+ data

Key Concepts

Local Table

The actual table on each shard node storing a partition of the data. Each shard has a local table with the same structure.

Distributed Table

A virtual table that references all local tables across the cluster. Queries to it are automatically distributed.

Sharding Key

The column used to determine which shard gets which data. Must distribute evenly across shards.

Replica

A copy of each shard for fault tolerance. Can be combined with sharding for maximum resilience.

Distributed Table Architecture

Client Application
Sends query to Distributed Table
↓
Distributed Table (Virtual)
Routes query to appropriate shards based on sharding key
↓ Query Distribution ↓
Shard 1
Local Table
events_local
Data: user_id 1-1M
Shard 2
Local Table
events_local
Data: user_id 1M-2M
Shard 3
Local Table
events_local
Data: user_id 2M-3M
↓ Parallel Execution ↓
Query Coordinator
Collects and merges results from all shards
↓
Final Result to Client

Sharding Key Distribution

Sharding Function
cityHash64(user_id) % 3
Shard 1 (33.3%)
Users:
user_1 user_4 user_7 user_10 ...
Shard 2 (33.3%)
Users:
user_2 user_5 user_8 user_11 ...
Shard 3 (33.3%)
Users:
user_3 user_6 user_9 user_12 ...
Key Properties:
  • Even distribution across all shards
  • Consistent hashing: same user_id always goes to same shard
  • Single-shard queries when filtering by user_id

Query Execution Flow

Single-Shard Query (Fast)

SELECT * FROM events
WHERE user_id = 12345
AND date >= '2026-01-01'
Step 1: Hash user_id
cityHash64(12345) % 3 = 1
↓
Step 2: Route to Shard 2
Query only 1 shard
↓
βœ… Fast: ~100ms

Multi-Shard Query (Scatter-Gather)

SELECT event_type, COUNT(*)
FROM events
WHERE date >= '2026-01-01'
GROUP BY event_type
Step 1: Broadcast to ALL shards
No user_id filter
↓
Step 2: Parallel Execution
All 3 shards process in parallel
↓
⚠️ Slower: ~1-2s

Cluster Architecture

πŸš€ Quick Start

1. Setup a 2-Node ClickHouse Cluster

Using Docker (Simplest for Testing)

2. Create Local Tables on Each Node

3. Create Distributed Table (Query All Shards)

4. Insert Data

5. Query Across Shards

πŸ’» Commands Reference

Cluster Configuration

Create Local Tables

✨ Best Practices

1. Choosing the Right Sharding Key

❌ Bad
βœ… Good

2. Shard Key Selection Criteria

Criterion Description Example
Cardinality High cardinality (millions of unique values) ensures even distribution user_id (good) vs country (bad)
Immutability Should not change over time (reshaping is expensive) user_id (good) vs status (bad)
Access Pattern Queries should frequently filter by shard key for efficiency WHERE user_id = X (good)
Uniformity Values should be uniformly distributed Sequential IDs (good) vs timestamps (bad)

3. Local vs Distributed Tables

Local Tables

  • Exist on each shard node
  • Store actual data
  • Use MergeTree family
  • Queries return partial results
  • Used internally by Distributed tables

Distributed Tables

  • Virtual tables (no data storage)
  • Reference local tables on shards
  • Route queries to appropriate shards
  • Combine results from all shards
  • Transparent horizontal scaling

4. Resharding Considerations

Resharding is EXPENSIVE and RISKY

Plan your sharding key carefully from the start. Resharding (changing the shard key or number of shards) requires:

  • Dropping and recreating all tables
  • Re-inserting all data (can take hours/days for large datasets)
  • Application downtime during migration

Recommendation: Choose your sharding strategy carefully initially. If unsure, start with 4-8 shards (easy to grow, hard to shrink).

5. Handling Uneven Distribution

🎯 When to Use Sharding

βœ… Use Sharding When

  • Data exceeds single server capacity (100TB+)
  • Query latency is critical (need parallelization)
  • Ingestion rate requires multiple nodes
  • Geographic distribution needed (regional shards)
  • Different data retention per shard
  • High availability is mandatory
  • Cost optimization via horizontal scaling

❌ Don't Use Sharding When

  • Data fits on single server (< 50TB)
  • Queries are simple and fast
  • Team lacks experience with distributed systems
  • Adding infrastructure complexity isn't justified
  • JOIN queries are frequent (costly across shards)
  • Transactions are critical (weak ACID support)
πŸ† Real-World Results
10x

Query Speed Improvement

Parallelizing across 10 shards reduces query time by ~90% (10x speedup)

1PB+

Scalable Data Volume

Handle petabytes of data across clusters with transparent sharding

99.9%

High Availability

Combined with replication, achieve 99.9%+ uptime

50%

Cost Reduction

Scale efficiently with commodity hardware, reduce per-node requirements

Use Case Examples

Case Study: Multi-Regional Analytics Platform

Challenge: 500 billion events/day across 15 countries

Solution: 3 shards Γ— 3 replicas (9 total nodes, geographically distributed)

Results:

  • Query latency: < 2 seconds for global queries
  • Ingestion: 5.7M events/second sustained
  • Regional failover: < 30 seconds RTO
  • Cost per event: 10x lower than data warehouse

Case Study: Financial Time-Series System

Challenge: 2 trillion data points (market data, trades, quotes)

Solution: 8 shards (partitioned by market + symbol hash)

Results:

  • Storage: 15TB raw data in 2TB compressed
  • P99 query latency: 500ms on 1-year lookback
  • Backfill performance: 100M points/sec per node
πŸ“‹ Ready-to-Use Templates

Template 1: Basic 3-Node Cluster Setup

πŸ”₯ Advanced Patterns

1. Asymmetric Sharding (Variable Shard Sizes)

πŸ“š Resources & Next Steps

πŸ“˜ View in Notion

Access this module in your Notion workspace for note-taking and tracking your progress.

Open in Notion β†’

πŸ› οΈ Tools & Utilities

  • ClickHouse Client - CLI for queries
  • DBeaver - GUI management tool
  • Tabix - Web UI for ClickHouse
  • ch-go - Go client library

πŸ’¬ Community & Support

Key Takeaways

  • βœ… Sharding = Horizontal Scaling: Distribute data across nodes for unlimited capacity
  • βœ… Shard Key is Critical: Choose wisely; resharding is expensive and risky
  • βœ… Local + Distributed: Local tables store data, Distributed tables query them
  • βœ… Combine with Replication: Sharding + replication provides both scale and reliability
  • βœ… Monitor Distribution: Uneven shards degrade performance; use system.parts to monitor

Next: Module 4 - Advanced Query Optimization

After mastering sharding, you'll learn:

  • Query optimization techniques for large datasets
  • Materialized views for pre-aggregation
  • Window functions and advanced analytics
  • Performance profiling and troubleshooting

🐳 Hands-on Docker Demo for this Module

A self-contained ClickHouse stack you can run locally. Every step is reproducible; the README below walks through each concept with diagrams and measured outcomes.

cd code-examples/demos/module-3-sharding
./up.sh        # bring stack up, wait for health
./run.sh       # run the demo (idempotent β€” re-runnable)
./down.sh      # tear down + drop volumes

πŸ“Ί Live demo capture

Recorded with vhs: the actual terminal output from ./run.sh running on this very stack.

Module demo GIF
Animated GIF, ~1160 KB. Right-click β†’ open in new tab to view full-size.

✨ Animated concept diagrams

Inline SVG animations β€” no plugins, native browser playback. Each visualises a key flow this module covers.

Sharding fanout
Sharding fanout

πŸ—‚οΈ Architecture diagrams

Rendered from the README's Mermaid sources. Click any to open the source SVG full-size.

Subgraph zk zookeeper keeper ensemble 3
Subgraph zk zookeeper keeper ensemble 3
Actor client
Actor client
Actor client
Actor client

πŸ“š ClickHouse reference visuals

Curated from the official ClickHouse documentation and engineering blog (and Altinity's docs/blog) β€” the same diagrams the broader CH community uses to explain these concepts. Click any image to read the source.

A single MergeTree table that has outgrown one server
ClickHouse Docs A single MergeTree table that has outgrown one server
Table data split into shards across multiple servers
ClickHouse Docs Table data split into shards across multiple servers
INSERT into a Distributed table: rows routed to target shards
ClickHouse Docs INSERT into a Distributed table: rows routed to target shards
SELECT fan-out: query forwarded to all shards, results merged
ClickHouse Docs SELECT fan-out: query forwarded to all shards, results merged
Horizontal scaling via sharding (architecture overview)
ClickHouse Docs Horizontal scaling via sharding (architecture overview)

πŸ“š Full module reference

Module 3 β€” Sharding & Distributed Tables

Audience: anyone scaling ClickHouse beyond one node. Prerequisites: Modules 1–2. Time: ~75 min reading + 30 min hands-on.

By the end you will be able to:


1. Why shard?

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Why shard?".

Here is a brief excerpt from the material I'm reading:

"""
A single ClickHouse node fits a remarkable amount of data β€” many teams run a single-node setup well into the **multi-TB** range. You shard when: | Reason                                | Symptom                                                         | | Data exceeds disk capacity            | `du -sh /var/lib/clickhouse` approaches the disk limit.          | | Query CPU saturated on one box        | `system.metrics.Query` always at the thread limit.               | | Background merges can't keep up       | `Too many parts` errors despite batched inserts.                 | | Network ingress >...
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

A single ClickHouse node fits a remarkable amount of data β€” many teams run a single-node setup well into the multi-TB range. You shard when:

Reason Symptom
Data exceeds disk capacity du -sh /var/lib/clickhouse approaches the disk limit.
Query CPU saturated on one box system.metrics.Query always at the thread limit.
Background merges can't keep up Too many parts errors despite batched inserts.
Network ingress > one NIC INSERT throughput pegged at the NIC's line rate.

If none of these are true: don't shard yet. A shard adds complexity to DDL, queries, and operations.


2. The cluster shape used by every cluster module in this repo

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "The cluster shape used by every cluster module in this repo".

Here is a brief excerpt from the material I'm reading:

"""
**3 shards Γ— 2 replicas = 6 ClickHouse processes + 3 ZooKeeper.** Every shard's two replicas hold identical data. Different shards hold *different* data, partitioned by the **sharding key**.
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

3 shards Γ— 2 replicas = 6 ClickHouse processes + 3 ZooKeeper. Every shard's two replicas hold identical data. Different shards hold different data, partitioned by the sharding key.


3. The two-table pattern

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "The two-table pattern".

Here is a brief excerpt from the material I'm reading:

"""
A sharded table is **two tables**, both created on every node: | Table                   | Engine                  | Where                       | Purpose                                            | | `hits_local`            | `ReplicatedMergeTree`   | physical, on each replica   | Actually stores the rows.                          | | `hits_distributed`      | `Distributed`           | logical, on each replica    | Fans inserts/reads across shards.                  | **`{shard}` and `{replica}` are macros**, expanded per-node from `configs/macros/macros-sNrM.xml` (Module 4 dives into this).
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

A sharded table is two tables, both created on every node:

Table Engine Where Purpose
hits_local ReplicatedMergeTree physical, on each replica Actually stores the rows.
hits_distributed Distributed logical, on each replica Fans inserts/reads across shards.
-- Created ONCE with ON CLUSTER, materialised on every node.
CREATE TABLE hits_local ON CLUSTER clickhouse_cluster (
    event_time DateTime,
    user_id    UInt64,
    country    LowCardinality(String),
    bytes      UInt32
)
ENGINE = ReplicatedMergeTree(
    '/clickhouse/tables/{shard}/hits_local',  -- ZK path: per-shard
    '{replica}'                                -- replica id within the shard
)
PARTITION BY toYYYYMM(event_time)
ORDER BY (user_id, event_time);

CREATE TABLE hits_distributed ON CLUSTER clickhouse_cluster
AS hits_local
ENGINE = Distributed(
    'clickhouse_cluster',     -- cluster name from <remote_servers>
    default,                  -- target database
    hits_local,               -- target table
    cityHash64(user_id)       -- sharding key
);

{shard} and {replica} are macros, expanded per-node from configs/macros/macros-sNrM.xml (Module 4 dives into this).


4. The cluster config β€” <remote_servers>

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "The cluster config β€” &lt;remote_servers&gt;".

Here is a brief excerpt from the material I'm reading:

"""
(no excerpt β€” section heading was "The cluster config β€” &lt;remote_servers&gt;")
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

This is the source of truth for "what's a shard, what's a replica":

<remote_servers>
    <clickhouse_cluster>
        <shard>
            <internal_replication>true</internal_replication>
            <replica><host>m3-s1r1</host><port>9000</port></replica>
            <replica><host>m3-s1r2</host><port>9000</port></replica>
        </shard>
        <shard>
            <internal_replication>true</internal_replication>
            <replica><host>m3-s2r1</host><port>9000</port></replica>
            <replica><host>m3-s2r2</host><port>9000</port></replica>
        </shard>
        <shard>
            <internal_replication>true</internal_replication>
            <replica><host>m3-s3r1</host><port>9000</port></replica>
            <replica><host>m3-s3r2</host><port>9000</port></replica>
        </shard>
    </clickhouse_cluster>
</remote_servers>
Element Effect
<shard> Defines a shard. Order matters β€” first <shard> is shard 1.
<replica> One CH process within the shard. All replicas of a shard hold identical data.
<weight> (optional) Default 1. Higher weight = bigger share of new inserts. See Β§8.
<internal_replication> Critical knob. See Β§6.
<user> / <password> Inter-server auth (if you set CH passwords).

Read it with SQL:

SELECT cluster, shard_num, replica_num, host_name, port
FROM system.clusters WHERE cluster = 'clickhouse_cluster'
ORDER BY shard_num, replica_num;

5. INSERT lifecycle β€” what happens when you insert into a Distributed table

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "INSERT lifecycle β€” what happens when you insert into a Distributed table".

Here is a brief excerpt from the material I'm reading:

"""
Key facts: - **Distributed INSERT is asynchronous by default.** The client gets an ack once the row is on the initiator's local spool, *before* it's been forwarded to each shard. Use `SYSTEM FLUSH DISTRIBUTED` to wait for all forwards to land. - **The initiator sends to *one* replica per shard** when `internal_replication = true`. That replica then replicates to its peer via ZK + interserver port (Module 4). - **The spool lives on disk** under `data/<db>/<distributed_table>/<shard>/`. If the initiator crashes, the spool survives.
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

Key facts:


6. internal_replication β€” the most-confused knob in CH

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "internal_replication β€” the most-confused knob in CH".

Here is a brief excerpt from the material I'm reading:

"""
(no excerpt β€” section heading was "internal_replication β€” the most-confused knob in CH")
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

Two modes, mutually exclusive at the cluster-config level:

Mode A β€” <internal_replication>true</internal_replication> (the right answer 99% of the time)

The Distributed engine sends to one replica per shard. ReplicatedMergeTree takes care of replication via ZK.

INSERT β†’ Distributed β†’ pick one replica per shard
                       ↓
                       write to s1r1
                       ↓
                       s1r1 logs part in ZK
                       ↓
                       s1r2 fetches part from s1r1 via :9009
Pro Con
One write per shard, not N. Requires Replicated*MergeTree.
Inherits ZK consistency guarantees. Requires ZK to be healthy.

Mode B β€” <internal_replication>false</internal_replication> (legacy)

The Distributed engine sends to every replica per shard. The local table can be plain MergeTree.

INSERT β†’ Distributed β†’ write to s1r1 AND s1r2 in parallel
Pro Con
No ZK dependency for replication. Network bandwidth = NΓ—.
Simpler local table engine. No deduplication; replicas can drift on partial fails.

Use internal_replication=true with ReplicatedMergeTree everywhere. The non-replicated path is mostly historical and fragile.


7. SELECT lifecycle β€” scatter / gather

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "SELECT lifecycle β€” scatter / gather".

Here is a brief excerpt from the material I'm reading:

"""
- The initiator picks **one replica per shard** for the read (load-balanced via `<load_balancing>` setting, default `random`). - Each shard runs a **partial aggregation** locally and sends the intermediate result up. The initiator merges. - For pre-filtered queries (`WHERE user_id = 42` with the demo's sharding key), the planner narrows to **a single shard** β€” visible in `EXPLAIN`.
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

8. Choosing a sharding key

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Choosing a sharding key".

Here is a brief excerpt from the material I'm reading:

"""
The sharding key is an arbitrary expression. The Distributed engine computes `key % total_weight` to pick a shard. | Key                              | Distribution         | Locality                                | Verdict for typical analytics       | | `cityHash64(user_id)`            | even                 | all events for one user β†’ one shard      | **Default choice.**                 | | `xxHash64(user_id)`              | even                 | same as above; lower collision rate      | Fine alternative.                    | | `intDiv(user_id, 100000)`        | even (if user_ids dense)...
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

The sharding key is an arbitrary expression. The Distributed engine computes key % total_weight to pick a shard.

Key Distribution Locality Verdict for typical analytics
cityHash64(user_id) even all events for one user β†’ one shard Default choice.
xxHash64(user_id) even same as above; lower collision rate Fine alternative.
intDiv(user_id, 100000) even (if user_ids dense) range scans on user_id stay shard-local Good when you query by user_id range
rand() even none β€” every query fans to all shards Avoid unless you never filter by key
cityHash64(toString(toDate(ts))) uneven (skews to today) recent reads scoped to one shard Time-skewed; hot-shard risk
cityHash64(country) very uneven all rows for a country on one shard Avoid for high-skew dimensions

Visual: the same data, four sharding keys

1M events with 250k distinct user_ids, 3 shards (weights 1,1,1):

cityHash64(user_id):     shard 1: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  333k
                          shard 2: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  334k
                          shard 3: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  333k

intDiv(user_id, 100000): shard 1: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  333k    (user_ids 0-99999 etc.)
                          shard 2: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  333k
                          shard 3: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  334k

rand():                  shard 1: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  333k    (random β€” no locality)
                          shard 2: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  334k
                          shard 3: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  333k

cityHash64(country):     shard 1: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  580k  (US + IN)
                          shard 2: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  170k
                          shard 3: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  250k
                          β–² HOT SHARD β€” avoid

Rule of thumb: the sharding key should be a stable, high-cardinality identifier that your queries already filter on (user_id, account_id, device_id). Time alone is a bad sharding key. Country alone is a bad sharding key.


9. Weighted shards β€” heterogeneous capacity

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Weighted shards β€” heterogeneous capacity".

Here is a brief excerpt from the material I'm reading:

"""
When one node is bigger than the others, set `<weight>` proportionally. The Distributed engine sums the weights and routes by `hash % total`. Above: `4/6 β‰ˆ 67%` of inserts go to shard 3. The demo's `extras.sql` defines a `weighted_cluster` over the same hosts and shows the resulting per-shard balance.
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

When one node is bigger than the others, set <weight> proportionally.

<weighted_cluster>
    <shard><weight>1</weight> ... s1 hosts ... </shard>
    <shard><weight>1</weight> ... s2 hosts ... </shard>
    <shard><weight>4</weight> ... s3 hosts ... </shard>   <!-- beefy node -->
</weighted_cluster>

The Distributed engine sums the weights and routes by hash % total. Above: 4/6 β‰ˆ 67% of inserts go to shard 3.

The demo's extras.sql defines a weighted_cluster over the same hosts and shows the resulting per-shard balance.


10. Other table functions for ad-hoc cluster queries

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Other table functions for ad-hoc cluster queries".

Here is a brief excerpt from the material I'm reading:

"""
| Function                            | Hits                                  | Use for                                  | | `cluster('cluster_name', db, tbl)`  | one replica per shard                 | one-shot fan-out without a Distributed table | | `clusterAllReplicas('...', db, tbl)`| **every replica of every shard**       | replica-equivalence checks, *never aggregations* | | `remote('host:port', db, tbl)`      | one specific node                     | cross-cluster spot queries               | | `remoteSecure(...)`                 | same, over TLS                        | as above, in pr...
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.
Function Hits Use for
cluster('cluster_name', db, tbl) one replica per shard one-shot fan-out without a Distributed table
clusterAllReplicas('...', db, tbl) every replica of every shard replica-equivalence checks, never aggregations
remote('host:port', db, tbl) one specific node cross-cluster spot queries
remoteSecure(...) same, over TLS as above, in production

Don't aggregate over clusterAllReplicas β€” you'll double-count.


11. The hands-on demo

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "The hands-on demo".

Here is a brief excerpt from the material I'm reading:

"""
### What you get ### Container map | Role        | Container | Host HTTP | Host TCP | | Shard 1 R1  | `m3-s1r1` | 8123      | 9000     | | Shard 1 R2  | `m3-s1r2` | 8124      | 9001     | | Shard 2 R1  | `m3-s2r1` | 8125      | 9002     | | Shard 2 R2  | `m3-s2r2` | 8126      | 9003     | | Shard 3 R1  | `m3-s3r1` | 8127      | 9004     | | Shard 3 R2  | `m3-s3r2` | 8128      | 9005     | | ZK 1/2/3    | `m3-zk1/2/3` | (internal) | | ### Execution flow β€” what runs, in order | #  | Step                                | What happens...
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

What you get

docker-compose.yml          9 containers: 3 ZK + 6 ClickHouse, prefix m3-
configs/cluster-node.xml    <remote_servers> + ZK + 2 cluster definitions
configs/macros/macros-s{1-3}r{1-2}.xml   per-node {shard}/{replica}
setup.sql Β· data.sql Β· queries.sql Β· extras.sql
up.sh Β· run.sh Β· down.sh

Container map

Role Container Host HTTP Host TCP
Shard 1 R1 m3-s1r1 8123 9000
Shard 1 R2 m3-s1r2 8124 9001
Shard 2 R1 m3-s2r1 8125 9002
Shard 2 R2 m3-s2r2 8126 9003
Shard 3 R1 m3-s3r1 8127 9004
Shard 3 R2 m3-s3r2 8128 9005
ZK 1/2/3 m3-zk1/2/3 (internal)

Execution flow β€” what runs, in order

# Step What happens
0 self-bootstrap If m3-s1r1 doesn't respond to /ping, up.sh runs first. Tears down peer demo modules, brings up the cluster, waits for every CH node to answer /ping.
1 setup.sql (via m3-s1r1) Three ON CLUSTER statements: drop any existing tables, then CREATE TABLE hits_local … ReplicatedMergeTree('/clickhouse/tables/{shard}/hits_local', '{replica}') on every node, then a Distributed('clickhouse_cluster', default, hits_local, cityHash64(user_id)) wrapper. The {shard} and {replica} macros are expanded per-node.
2 data.sql (via m3-s1r1) One INSERT INTO hits_distributed SELECT FROM numbers(5_000_000). The Distributed table fans rows to the right hits_local based on cityHash64(user_id) % 3.
3 SYSTEM FLUSH DISTRIBUTED Γ— 6 Distributed inserts spool briefly on each node. Flushed on every replica so the next counts are exact.
4 queries.sql Six queries: cluster topology, total rows, per-shard breakdown, replica equivalence, country aggregation, EXPLAIN, single-shard point lookup.
5 extras.sql Sets up weighted_cluster (weights 1,1,4) β†’ 600k row insert β†’ per-shard balance (~66% on shard 3). Then three more Distributed tables with alternative sharding keys (rand(), intDiv(), xxHash64()) and EXPLAIN for each.

What to look for

Step Outcome
system.clusters 3 shards Γ— 2 replicas, all errors_count = 0.
Per-shard count ~1.67M rows each (5M / 3 with cityHash64).
Replica equivalence (s1) r1 and r2 have identical byte counts.
EXPLAIN … WHERE user_id = 42 Plan shows query goes to one shard.
Weighted cluster balance ~100k / 100k / 400k (shard 3 has 4Γ— weight).

12. Operational SQL cheatsheet

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Operational SQL cheatsheet".

Here is a brief excerpt from the material I'm reading:

"""
(no excerpt β€” section heading was "Operational SQL cheatsheet")
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.
-- "Is the cluster healthy?"
SELECT cluster, shard_num, replica_num, host_name, errors_count, slowdowns_count
FROM system.clusters WHERE cluster = 'clickhouse_cluster';

-- "How many rows on each shard, right now?"
SELECT shardNum() AS shard, count() AS rows
FROM clusterAllReplicas('clickhouse_cluster', default, hits_local)
GROUP BY shard ORDER BY shard;

-- "What's pending in the distributed spool?"
SELECT database, table, is_blocked, error_count, data_files, data_compressed_bytes
FROM system.distribution_queue;

-- "What did this query actually do?"
EXPLAIN SELECT count() FROM hits_distributed WHERE user_id = 42;

13. Common pitfalls

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Common pitfalls".

Here is a brief excerpt from the material I'm reading:

"""
| Symptom                                                                 | Cause                                                                  | Fix                                                                                              | | One shard has 4Γ— the rows of others                                     | High-skew sharding key (e.g. `country`).                               | Re-shard with a high-cardinality key or use a composite expression.                              | | `INSERT INTO hits_distributed` returns immediately, but `SELECT count()` is short | Spool not yet flus...
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.
Symptom Cause Fix
One shard has 4Γ— the rows of others High-skew sharding key (e.g. country). Re-shard with a high-cardinality key or use a composite expression.
INSERT INTO hits_distributed returns immediately, but SELECT count() is short Spool not yet flushed. SYSTEM FLUSH DISTRIBUTED <table> on every node.
Replicas on the same shard disagree on row count internal_replication = false + a partial-failure write. Switch to internal_replication = true and ReplicatedMergeTree.
EXPLAIN shows scatter even though WHERE filters by sharding key The planner couldn't statically prove the filter narrows to one shard. Filter must be on the exact column expression of the sharding key.
ON CLUSTER DDL hangs distributed_ddl_task_timeout exceeded; one node unhealthy. Check system.distributed_ddl_queue.exception_text; fix the unhealthy node.
Changing <remote_servers> doesn't take effect XML reloads on file change; if it didn't, you may have a parse error. SELECT * FROM system.clusters to confirm; check server log for parse errors.

14. Talking points for the live session

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Talking points for the live session".

Here is a brief excerpt from the material I'm reading:

"""
1. **Sharding β‰  partitioning.** Walk through the layered mental model: *cluster β†’ shard β†’ replica β†’ partition β†’ part β†’ granule.* 2. **Sharding key = locality + uniformity.** Show why `country` is bad (skew) and `cityHash64(user_id)` is good (even, but stable). 3. **`internal_replication` is the knob most teams get wrong.** Show the two flow diagrams and recommend `true` + Replicated. 4. **`SYSTEM FLUSH DISTRIBUTED`** isn't optional in tests β€” it's the reason your CI's flaky. 5. **Weighted shards** for heterogeneous fleets. Demo the 1/1/4 cluster and `system.clusters.weight`. 6. **Resharding is...
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.
  1. Sharding β‰  partitioning. Walk through the layered mental model: cluster β†’ shard β†’ replica β†’ partition β†’ part β†’ granule.
  2. Sharding key = locality + uniformity. Show why country is bad (skew) and cityHash64(user_id) is good (even, but stable).
  3. internal_replication is the knob most teams get wrong. Show the two flow diagrams and recommend true + Replicated.
  4. SYSTEM FLUSH DISTRIBUTED isn't optional in tests β€” it's the reason your CI's flaky.
  5. Weighted shards for heterogeneous fleets. Demo the 1/1/4 cluster and system.clusters.weight.
  6. Resharding is a project, not a setting. Use clickhouse-copier or write to a parallel cluster with the new key, then cut over.

15. Going deeper

πŸ’¬ Discuss with AI β€” click to view prompt
Paste into ChatGPT, Claude, Gemini, or any LLM chat.
I'm studying ClickHouse and working through the module "ClickHouse Sharding & Distributed Tables". I want to deeply understand the section: "Going deeper".

Here is a brief excerpt from the material I'm reading:

"""
- **Module 4** β€” what ZK actually does for replication, with kill-replica drills. - **Module 5** β€” `ON CLUSTER` DDL, distributed query plans, `cluster()` table function. - **Module 8** β€” disaster recovery on this same cluster.
"""

Please explain this concept in depth. Cover:

1. **Core mechanics** β€” how does it actually work under the hood? What data structures, algorithms, or engine internals are involved? Where is the implementation in the ClickHouse source tree (file/folder names) if you know?

2. **When to use vs avoid** β€” what concrete workloads does this help, and when would it hurt or be wrong? Give specific scale/latency trade-offs.

3. **Comparable features in other systems** β€” how does this compare with similar features in PostgreSQL, MySQL, BigQuery, Snowflake, Redshift, or DuckDB? Build my intuition by analogy.

4. **Common pitfalls and gotchas** β€” what trips engineers up in production? Subtle bugs, performance traps, surprising semantics?

5. **Worked example** β€” show me a small but realistic SQL or config example that demonstrates the concept end-to-end. Include the expected output where useful.

6. **Where to read more** β€” a short list of authoritative pointers (CH docs, blog posts, talks, source-code files).

Assume I have solid SQL fundamentals but I'm new to ClickHouse internals. Be technical but pragmatic; avoid marketing language.

πŸ”€ ClickHouse Sharding & Distribution

Module 3 of 10 | Duration: 6-8 weeks total

Master distributed architecture for unlimited scalability | 2026

← Previous: Module 2 - Table Engines 🏠 Home Next: Module 4 - Replication β†’