clickhouse/clickhouse
Architecture
ClickHouse is a columnar OLAP database written in C++23. A single binary, dispatched by programs/main.cpp, hosts the server, the clients, the embedded engine (clickhouse-local), and the Raft coordination service (clickhouse-keeper). All of these share the same engine code under src/.
This page sketches the request lifecycle and the major subsystems. Each subsystem has its own wiki page under systems/.
Birds-eye view
graph TD
Client[Clients<br/>HTTP / Native TCP / MySQL / Postgres / gRPC] --> Server[programs/server<br/>src/Server]
Server --> Parsers[src/Parsers<br/>SQL → AST]
Parsers --> Analyzer[src/Analyzer<br/>QueryTree, name resolution, types]
Analyzer --> Planner[src/Planner<br/>logical → physical plan]
Planner --> Pipeline[src/QueryPipeline + src/Processors<br/>operator graph]
Pipeline --> Storages[src/Storages<br/>MergeTree, Distributed, ObjectStorage, Kafka, ...]
Storages --> Disks[src/Disks + src/IO<br/>local FS, S3, Azure, HDFS, web]
Pipeline --> Functions[src/Functions + src/AggregateFunctions]
Server -.metadata.-> Coord[src/Coordination<br/>clickhouse-keeper / ZooKeeper]
Storages -.metadata.-> CoordThe request lifecycle
A SELECT arrives at the server through one of the protocol handlers (HTTPHandler, TCPHandler, MySQL/Postgres/gRPC/ArrowFlight in src/Server/). Each handler creates a per-query Context (src/Interpreters/Context.h) that carries the user, settings, access rights, and ClientInfo.
- Parse.
src/Parsers/turns the SQL text into an AST (ASTSelectQuery,ASTInsertQuery, …).parseQuery.cppis the entry point. - Analyze. With
enable_analyzer=1(the default since v24.x), the parser AST is converted into aQueryTreebysrc/Analyzer/QueryTreeBuilder.cpp. The analyzer resolves names, expands*, infers types, normalizes joins, and fixes pass-types. The legacy path goes throughsrc/Interpreters/InterpreterSelectQuery.cppandExpressionAnalyzer.cppinstead. - Plan.
src/Planner/Planner.cppwalks theQueryTreeand emits aQueryPlan(src/Processors/QueryPlan/) — a tree of logical steps (ReadFromMergeTree,FilterStep,AggregatingStep,JoinStep,LimitStep, …). - Optimize.
QueryPlanOptimizationsapply rule-based passes: predicate pushdown, projection use, filter merging,ORDER BYremoval,IN-set lifting, distributed-aware reordering. - Build the pipeline. Each step builds processors (
src/Processors/). A processor is a node in a pull-based dataflow graph with input and output ports (Port.h,IProcessor.h). The graph is executed bysrc/Processors/Executors/PipelineExecutor.cppover a thread pool. - Read. Source processors (
MergeTreeSource,RemoteSource,KafkaSource, …) emitChunks of column data.Chunkwraps aColumnsarray plus row count. - Transform. Filters, aggregations, joins, sorting, window functions, and projections are implemented as
ITransformsubclasses. Heavy state (hash tables, sort buffers, join indexes) lives insrc/Interpreters/. - Sink. For
SELECTthe finalChunkstream is serialized into the requestedFormat(src/Formats/) and written back to the client. ForINSERTthe sink writes a new part into the storage engine.
Storage layer
graph LR
SQL[INSERT/SELECT] --> Storage[IStorage<br/>src/Storages]
Storage --> MT[StorageMergeTree<br/>StorageReplicatedMergeTree]
Storage --> Dist[StorageDistributed]
Storage --> Obj[ObjectStorage<br/>S3/Azure/HDFS]
Storage --> Stream[Kafka / NATS / RabbitMQ / FileLog]
Storage --> Memory[Memory / Buffer / Set / Join]
Storage --> External[MySQL / Postgres / Mongo / Redis / SQLite]
MT --> Parts[Data Parts<br/>granules + marks + columns]
Parts --> Disk[IDisk<br/>local / s3 / azure / web / cache]
MT -.coordination.-> Keeper[clickhouse-keeper / ZooKeeper]IStorage (src/Storages/IStorage.h) is the abstract base for every table engine. MergeTree is the workhorse: it writes rows as immutable, sorted, columnar parts that are later merged in the background. Mutations are themselves merges that rewrite the affected ranges. Replication uses the Keeper-backed log in StorageReplicatedMergeTree.
Object-storage engines (StorageS3, StorageAzure, StorageHDFS, StorageIceberg, StorageDeltaLake, StorageHudi) live under src/Storages/ObjectStorage/. They share a common abstraction (IObjectStorage in src/Disks/ObjectStorages/) so the same code reads MergeTree parts from a bucket as reads *.parquet files from a bucket.
The execution engine
src/Processors/ implements a pull-based, push-back-pressured operator graph. Each processor exposes a status (NeedData, PortFull, Ready, Async, ExpandPipeline, Finished) and a work() method. The PipelineExecutor walks the graph, picks ready processors, and runs them on a thread pool.
Key operator implementations live in src/Processors/Transforms/ and src/Processors/Merges/ — AggregatingTransform, MergingAggregatedTransform, MergeJoinTransform, SortingTransform, WindowTransform, LimitTransform, etc. The non-trivial algorithms (vectorized aggregation, hash join, merge join, gorilla compression, query JIT) are kept in src/Interpreters/Aggregator.cpp, src/Interpreters/HashJoin/, and src/Interpreters/ExpressionJIT.cpp.
Coordination and replication
Replicated tables and Keeper itself form ClickHouse's only stateful coordination layer. src/Coordination/ is a Raft implementation built on top of NuRaft (vendored in contrib/NuRaft) with a RocksDB-backed log (contrib/rocksdb) and an in-memory KV state machine (KeeperStateMachine.cpp, KeeperStorage.cpp). It speaks the ZooKeeper wire protocol so existing tooling works.
StorageReplicatedMergeTree writes a log of part operations to Keeper. Replicas pull entries, fetch parts from peers via an HTTP service (DataPartsExchange.cpp), and merge in the background. Distributed tables (src/Storages/StorageDistributed.cpp) are stateless query routers; sharding/replication is described in the cluster config (src/Interpreters/Cluster.cpp).
Cross-cutting concerns
- Type system (
src/DataTypes/,src/Columns/,src/Core/): every value passes through a typed columnar container.Blockis a vector of namedColumnpointers plus types.Fieldis the boxed scalar form used in interpretation. - Functions (
src/Functions/,src/AggregateFunctions/): each function is a class registered into a globalFunctionFactory. Most functions are vectorized overColumnand have specialized integer/float/string paths. - Settings (
src/Core/Settings.cpp,src/Core/ServerSettings.cpp,src/Storages/MergeTree/MergeTreeSettings.cpp): there are 1500+ runtime settings, registered via X-macros and queryable throughsystem.settings. - Access control (
src/Access/): users, roles, grants, row policies, quotas, settings profiles. Backed by RBAC stored either in XML/users.xmlor inIDiskAccessStorage/ Keeper. - Backups (
src/Backups/):BACKUPandRESTOREto local disk, S3, Azure, etc. Splits into entries and reuses the disks layer.
Configuration
Server config is XML or YAML (programs/server/config.xml, users.xml) with includes from config.d/ and users.d/. The schema is documented inline. At runtime the merged config is exposed in system.server_settings and system.settings.
Build system
CMake plus ninja, with clang mandatory. Top-level entry: CMakeLists.txt. Toolchain configuration lives in cmake/ and PreLoad.cmake. External libraries are in contrib/ (git submodules) plus a small Rust workspace in rust/. For build commands see Getting started.
Further reading
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.