clickhouse/clickhouse
clickhouse-local
clickhouse-local is the same database engine as clickhouse-server, packaged as a single-process tool that can be invoked from a shell script. Source: programs/local/.
Purpose
When you do not need a long-lived server but you do want to run SQL over local files, S3 buckets, or HTTP-served datasets, clickhouse-local boots the engine in-process, optionally creates a scratch storage area, runs your queries, and exits.
It is the most popular way to use ClickHouse for ad-hoc analytics and ETL one-liners. From the binary's universal-dispatch logic in programs/main.cpp:
Interpret binary without argument or with arguments starts with dash ('-') as
clickhouse-localfor better usability.
So clickhouse "select 1", clickhouse my_query.sql, and clickhouse -q '...' all route to local.
Source layout
| Path | Purpose |
|---|---|
programs/local/LocalServer.cpp |
The LocalServer class — orchestrates a one-shot engine. |
programs/local/LocalServer.h |
Declarations. |
programs/local/clickhouse-local.cpp |
Tiny shim. |
LocalServer derives from ClientBase (in src/Client/) so it shares the user-facing surface (formats, progress, prompts) with clickhouse-client. The engine itself is the same Context and IStorage machinery as the server.
How it works
- Argv parsing. Resolves a query (
-q, file argument, or stdin), an input file (--file), an input format, an output format, a working directory. - Constructs a global
Contextexactly likeServer::maindoes, but skips:- Network listeners.
- Replication /
clickhouse-keeperconnection. - Background pools (mostly).
- Persistent metadata loading from disk (unless
--pathpoints to a real data directory).
- Either creates a virtual
_localdatabase with the input file as a table, or mounts an existing data directory through--path. - Runs the supplied SQL via
executeQueryand renders the result to stdout in the chosen format. - Tears down the
Contextand exits.
Common patterns
# Query a CSV
clickhouse local -q "SELECT name, count() FROM file('events.csv', CSVWithNames) GROUP BY name"
# Query Parquet on S3 directly
clickhouse local -q "SELECT * FROM s3('https://.../events.parquet') WHERE eventName='page_view' LIMIT 10"
# Convert formats
clickhouse local -q "SELECT * FROM file('in.json', JSONEachRow) FORMAT Parquet" > out.parquet
# As a calculator
clickhouse local -q "SELECT exp(pi())"
# Pipe through stdin/stdout
cat in.csv | clickhouse local --input-format=CSV --output-format=JSON \
-q "SELECT col1, count() FROM table GROUP BY col1"Persistent vs ephemeral mode
By default clickhouse-local creates a temp directory and deletes it on exit. With --path /var/lib/clickhouse-data it acts on a real data directory, and any CREATE TABLE/INSERT is persisted. This makes clickhouse-local a viable single-node engine for cron jobs, embedded usage, and tests.
Why clickhouse-local and not just SQL?
- Zero configuration. You don't need to start a server.
- Direct access to file/S3/HTTP/HDFS/URL/Kafka via the same table functions as the server (
file,s3,url,hdfs,azureBlobStorage,iceberg,deltaLake, …). - Same query engine. The same
MergeTreeengine, the same vectorized executor, the same functions. - Composes with shells. Returns exit codes, can pipe.
Limitations
- No replication, no inter-server traffic, no
Distributedqueries by default. - Only one process — no concurrent clients.
- Long-lived background tasks (TTL moves, expensive merges) usually only fire once you start a server.
Entry points for modification
- To change the local-mode startup, edit
programs/local/LocalServer.cpp. Most of the moving parts come fromsrc/Client/ClientBase.cpp. - To support a new input format in
clickhouse-local --input-format=..., register the format insrc/Formats/FormatFactory.cpp(it then becomes available everywhere).
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.