Documentation Index
Fetch the complete documentation index at: https://private-7c7dfe99-page-updates.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Custom partitioning key
In most cases you do not need a partition key, and in most other cases you do not need a partition key more granular than by month, unless targeting an observability use case where partitioning by day is common.You should never use too granular of partitioning. Don’t partition your data by client identifiers or names. Instead, make a client identifier or name the first column in the ORDER BY expression.
PARTITION BY expr clause when creating a table. The partition key can be any expression from the table columns. For example, to specify partitioning by month, use the expression toYYYYMM(date_column):
A merge only works for data parts that have the same value for the partitioning expression. This means you shouldn’t make overly granular partitions (more than about a thousand partitions). Otherwise, the
SELECT query performs poorly because of an unreasonably large number of files in the file system and open file descriptors.visits table with partitioning by month. Let’s perform the SELECT query for the system.parts table:
partition column contains the names of the partitions. There are two partitions in this example: 201901 and 201902. You can use this column value to specify the partition name in ALTER … PARTITION queries.
The name column contains the names of the partition data parts. You can use this column to specify the name of the part in the ALTER ATTACH PART query.
Let’s break down the name of the part: 201901_1_9_2_11:
201901is the partition name.1is the minimum number of the data block.9is the maximum number of the data block.2is the chunk level (the depth of the merge tree it is formed from).11is the mutation version (if a part mutated)
The parts of old-type tables have the name:
20190117_20190123_2_2_0 (minimum date - maximum date - minimum block number - maximum block number - level).active column shows the status of the part. 1 is active; 0 is inactive. The inactive parts are, for example, source parts remaining after merging to a larger part. The corrupted data parts are also indicated as inactive.
As you can see in the example, there are several separated parts of the same partition (for example, 201901_1_3_1 and 201901_1_9_2). This means that these parts are not merged yet. ClickHouse merges the inserted parts of data periodically, approximately 15 minutes after inserting. In addition, you can perform a non-scheduled merge using the OPTIMIZE query. Example:
/var/lib/clickhouse/data/<database>/<table>/. For example:
detached directory contains parts that were detached from the table using the DETACH query. The corrupted parts are also moved to this directory, instead of being deleted. The server does not use the parts from the detached directory. You can add, delete, or modify the data in this directory at any time – the server will not know about this until you run the ATTACH query.
Note that on the operating server, you cannot manually change the set of parts or their data on the file system, since the server will not know about it. For non-replicated tables, you can do this when the server is stopped, but it isn’t recommended. For replicated tables, the set of parts cannot be changed in any case.
ClickHouse allows you to perform operations with the partitions: delete them, copy from one table to another, or create a backup. See the list of all operations in the section Manipulations With Partitions and Parts.
Group By optimisation using partition key
For some combinations of table’s partition key and query’s group by key it might be possible to execute aggregation for each partition independently. Then we’ll not have to merge partially aggregated data from all execution threads at the end, because we provided with the guarantee that each group by key value cannot appear in working sets of two different threads. The typical example is:Performance of such a query heavily depends on the table layout. Because of that the optimisation is not enabled by default.
- number of partitions involved in the query should be sufficiently large (more than
max_threads / 2), otherwise query will under-utilize the machine - partitions shouldn’t be too small, so batch processing won’t degenerate into row-by-row processing
- partitions should be comparable in size, so all threads will do roughly the same amount of work
It’s recommended to apply some hash function to columns in
partition by clause in order to distribute data evenly between partitions.allow_aggregate_partitions_independently- controls if the use of optimisation is enabledforce_aggregate_partitions_independently- forces its use when it’s applicable from the correctness standpoint, but getting disabled by internal logic that estimates its expediencymax_number_of_partitions_for_independent_aggregation- hard limit on the maximal number of partitions table could have