symbols and lines columns of system.trace_log, so the examples below read those columns directly and do not require introspection functions. Symbolization is controlled by the symbolize setting in the trace_log server configuration section (enabled by default) and is supported on ELF platforms (such as Linux) and macOS; on FreeBSD the symbols and lines columns are always empty. Function names in symbols come from the binary’s symbol table and are available by default. Source locations in lines are best-effort: they require debug info (on macOS, a .dSYM bundle next to the binary), and on ELF platforms only frames inside the main ClickHouse binary are resolved, so entries for frames that cannot be resolved (for example, in shared libraries) are left empty. If symbolization is disabled, use the addressToSymbol, demangle and addressToLine introspection functions to resolve the raw addresses in the trace column instead. These functions are available on the same platforms as symbolization (ELF platforms such as Linux, and macOS); on FreeBSD they are not compiled in either, so the addresses in trace have to be resolved outside the server.
- ClickHouse Cloud
- Self-managed
In ClickHouse Cloud, you can obtain the query ID by clicking ”…” on the far right of the bar above the query result table (next to the table/chart toggle). This opens a context menu where you can click “Copy query ID”.Use
clusterAllReplicas(default, system.trace_log) to select from all nodes of the cluster:Using the query profiler in self-managed deployments
In self-managed deployments, to use the query profiler follow the steps below:1
Install ClickHouse with debug info
Install the
clickhouse-common-static-dbg package:- Follow the instructions in step “Set up the Debian repository”
- Run
sudo apt-get install clickhouse-server clickhouse-client clickhouse-common-static-dbgto install ClickHouse compiled binary files with debug info - Run
sudo service clickhouse-server startto start the server - Run
clickhouse-client. The debug symbols from clickhouse-common-static-dbg will automatically be picked up by the server - you don’t need to do anything special to enable them
2
Check server config
Ensure that the This section configures the trace_log system table containing the results of the profiler functioning.
The
trace_log section of your server configuration file is set up. It is enabled by default:symbolize option (enabled by default) makes ClickHouse resolve each stack frame at collection time and store the demangled function names and source locations in the symbols and lines columns.
Function names in symbols come from the symbol table and are available by default, while source locations in lines require debug info (a .dSYM bundle on macOS) and, on ELF platforms, are resolved only for frames inside the main ClickHouse binary; unresolved frames have empty lines entries.Note that the raw addresses in the trace column are less stable across restarts and upgrades than the pre-symbolized columns.
On ELF platforms except FreeBSD, frames in the main ClickHouse binary are stored as physical file offsets, so they stay resolvable across restarts as long as the binary is unchanged; on macOS and FreeBSD they are stored as runtime virtual addresses that may become invalid after a restart.
Frames outside the main binary (for example, in shared libraries) are always stored as runtime virtual addresses that may become invalid after a restart, and any raw address becomes unresolvable after a binary upgrade because the code layout changes.
ClickHouse does not clean up the table on restart, so stale raw addresses can remain.
The pre-symbolized symbols and lines columns, on the other hand, remain valid across restarts and upgrades, so prefer them when analyzing historical data.3
Configure profile timers
Set up the
query_profiler_cpu_time_period_ns or query_profiler_real_time_period_ns settings.
Both settings can be used simultaneously.These settings allow you to configure profiler timers.
As these are the session settings, you can get different sampling frequency for the whole server, individual users or user profiles, for your interactive session, and for each individual query.The default sampling frequency is one sample per second, and both CPU and real timers are enabled.
This frequency allows you to collect sufficient information about your ClickHouse cluster whilst not affecting your server’s performance.
If you need to profile each individual query, use a higher sampling frequency.4
Analyze the trace_log system table
To get a profile for some query, you need to aggregate data from the Use the
trace_log table.
You can aggregate data by individual functions or by the whole stack traces.When symbolization is enabled (the default), the demangled function names and source locations are already available in the symbols and lines columns, so no additional setup is required. Symbolization is not supported on FreeBSD, where these columns are always empty. lines entries may be empty for frames that lack debug info or fall outside the main ClickHouse binary (see above).If symbolization is disabled, or you want to resolve the raw addresses in the trace column on the fly (for example, to expand inline frames), allow introspection functions with the allow_introspection_functions setting:For security reasons, introspection functions are disabled by default
addressToLine, addressToLineWithInlines, addressToSymbol and demangle introspection functions to get function names and their positions in ClickHouse code. Like symbolization, these functions are available on ELF platforms (such as Linux) and macOS, but not on FreeBSD.Building flame graphs with the flameGraph function
ClickHouse provides the flameGraph aggregate function which builds a flame graph directly from stack traces stored in trace_log.
The output is an array of strings in a format compatible with flamegraph.pl.
Syntax:
traces— a stacktrace.Array(UInt64).size— an allocation size for memory profiling.Int64.ptr— an allocation address.UInt64.
ptr is non-zero, flameGraph maps allocations (size > 0) and deallocations (size < 0) with the same size and pointer.
Only allocations that were not freed are shown.
Unmatched deallocations are ignored.
CPU flame graph
The queries below require you to have flamegraph.pl installed.You can do so by running:Replace
flamegraph.pl in the following queries with the path where flamegraph.pl is located on your machineMemory flame graph — all allocations
Memory flame graph — unfreed allocations
This variant matches allocations against deallocations by pointer and shows only memory that was not freed during the query.Memory flame graph — active allocations at a point in time
This approach lets you find peak memory usage and visualize what was allocated at that moment.Find memory usage over time
Find the time point with maximum memory usage
Build a flame graph of active allocations at that time point
Build a flame graph of deallocations after that time point (to understand what was freed later)
Example
The code snippet below:- Filters
trace_logdata by a query identifier and the current date. - Reads the pre-symbolized
symbolsandlinescolumns to build a report of:- The names of symbols and corresponding source code functions.
- The source code locations of these functions.
- Aggregates by the raw stack trace (the
tracecolumn), using the symbolized columns only for display, so that distinct stack traces are never collapsed by best-effort symbolization.