ClickHouse: Release 25.10 Call

ClickHouse Release 25.10

ClickHouse release 25.10

1. (55 min) What's new in ClickHouse 25.10.

2. (5 min) Q&A.

Release 25.10

ClickHouse Halloween Release.

โ€” 20 new features ๐Ÿ‘ป

โ€” 30 performance optimizations ๐Ÿ”ฎ

โ€” 103 bug fixes ๐ŸŽƒ

Small And Nice Features

Table Aliases

CREATE TABLE my_alias ENGINE = Alias(source_table); CREATE TABLE my_alias ENGINE = Alias(source_database, source_table);

References the existing table and forwards all operations to it
(except DROP, DETACH, and RENAME).

Good for migrations, to provide multiple names for a single table.

Developer: Kai Zhu.

Operator <=>

:) SELECT NULL = NULL 0 :) SELECT NULL <=> NULL 1

— equality comparison that treats NULLs as identical.

Also available as the IS NOT DISTINCT FROM operator.

This operator was previously available only for the JOIN ON section.

Developer: Simon Michal.

conv

:) SELECT conv('111', 10, 8) 157

Convert numbers between different bases (digits are 0..9A..Z).

Compatible with MySQL.

Note: we already have hex/unhex and bin/unbin functions.

Developer: hp77-creator.

LIMIT BY ALL

ClickHouse already supports a LIMIT BY clause,
which is an extension to DISTINCT.

Example: LIMIT 5 BY country
— take only first 5 records for each distinct country.

Can be even combined with LIMIT:
LIMIT 5 BY country LIMIT 100.

Now you can write LIMIT 5 BY ALL
— take up to 5 duplicate records.

Developer: Surya Kant Ranjan.

Column Statistics

Now you can enable statistics for all columns with a table-level setting:

CREATE TABLE test (...) ORDER BY () SETTINGS auto_statistics_types = 'minmax,uniq,countmin';

Or with a global configuration:

$ cat /etc/config.d/merge_tree.yaml merge_tree: auto_statistics_types: 'minmax,uniq,countmin'

Statistics are used for automatic JOIN reordering.

Developer: Anton Popov.

SYSTEM RECONNECT ZOOKEEPER

A new system query to re-establish a Keeper session.

If the distribution of connections between ClickHouse nodes and Keeper nodes became unbalanced or suboptimal, you can rebalance it with this command.

Developer: Pradeep Chhetri.

ALTER TABLE REWRITE PARTS

ALTER TABLE hits REWRITE PARTS; ALTER TABLE hits REWRITE PARTS IN PARTITION 202501;

A new mode for the ALTER TABLE query, useful for:

— re-encrypting the data after changing the encryption key;
— applying changes after modifying settings for physical data layout,
  such as compression block size;

It is faster than the OPTIMIZE query as it does not merge data parts.

Developer: Azat Khuzhin.

Performance Improvements

A new physical layout for String

The previous layout, default:
str.bin: 5Hello10ClickHouse

The new layout, with_size_stream:
str.bin: HelloClickHouse
str.size.bin: 510

CREATE TABLE ... SETTINGS serialization_info_version = 'with_types', string_serialization_version = 'with_size_stream';

Demo

Developer: Amos Bird.

"Replicated" Columns

What if a block of data multiplies many times during JOIN?

SELECT count() FROM hits; -- 100 million SELECT count() FROM hits AS t1 INNER JOIN hits AS t2 ON t1.ClientIP = t2.ClientIP; -- 40.18 billion

Now we can do it lazily, without spending memory and CPU!

:) SET enable_lazy_columns_replication;

Demo

Developer: Pavel Kruglov.

Bloom Filters in JOINs

To speed-up your queries:

:) SET enable_join_runtime_filters;

A small filter can be built from one JOIN side and
used as "PREWHERE" in another side while reading from the table.

Demo

Developer: Alexander Gololobov.

Push-down of complex conditions in JOINs

Let's say we have a combination of conditions for different tables:

SELECT * FROM n1 INNER JOIN n2 WHERE (n1.name = 'FRANCE' AND n2.name = 'GERMANY') OR (n1.name = 'GERMANY' AND n2.name = 'FRANCE');

This will automatically derive conditions for the left and right tables
and push-down these conditions.

:) SET use_join_disjunctions_push_down;

Developer: Yarik Briukhovetskyi.

Late materialization of secondary indices

Now you can postpone building the indices from the INSERT time
to background merges:

SET exclude_materialize_skip_indexes_on_insert;

Or even disable building indices during merges:

CREATE TABLE t (...) SETTINGS materialize_skip_indexes_on_merge = false;

Or exclude certain (heavy) indices from calculation:

CREATE TABLE t (...) SETTINGS exclude_materialize_skip_indexes_on_merge = 'vector_a,bf';

Developer: George Larionov.

Something Interesting

Negative LIMIT and OFFSET

Example: get 100 last records, but return them in the ascending order:

-- Before 25.10: :) SELECT * FROM ( SELECT * FROM logs WHERE date = today() ORDER BY time DESC LIMIT 100 ) ORDER BY time; -- Since 25.10: :) SELECT * FROM logs WHERE date = today() ORDER BY time LIMIT -100; -- negative pagination: LIMIT -100 OFFSET 100

Developers: Nihal Z. Miaji.

QBit Data Type ๐Ÿงช

A data type for vector embeddings,
that allows tuning the search precision at runtime.

CREATE TABLE vectors ( id UInt64, name String, ... vec QBit(BFloat16, 1536) ) ORDER BY ();

SELECT id, name FROM vectors ORDER BY L2DistanceTransposed(vector, target, 10) LIMIT 10;

Developer: Raufs Dunamalijevs.

QBit Data Type ๐Ÿงช

It uses a bit-sliced data layout:
every number is sliced by bits,
e.g., for 1536-dim vector of Float32,
we store 32 subcolumns with Nth (0..31th) bits from all dimensions.

At the query time, we specify, how many (most significant) bits to take.

For example, we can ask to read
only 10 out of 32 bits.

Developer: Raufs Dunamalijevs.

QBit Data Type ๐Ÿงช

Demo

CREATE TABLE dbpedia ( id String, title String, text String, vector Array(Float32) CODEC(NONE) ) ENGINE = MergeTree ORDER BY (id); seq 0 25 | xargs -P4 -I{} clickhouse-client "INSERT INTO dbpedia SELECT id, title, text, \"text-embedding-3-large-1536-embedding\" FROM url('https://huggingface.co/api/datasets/Qdrant/dbpedia-entities- openai3-text-embedding-3-large-1536-1M/parquet/default/train/{}.parquet') SETTINGS max_http_get_redirects = 5" SET allow_experimental_qbit_type = 1; ALTER TABLE dbpedia ADD COLUMN qbit QBit(Float32, 1536); ALTER TABLE dbpedia UPDATE qbit = vector WHERE 1;

Developer: Raufs Dunamalijevs.

Data Lakes

Apache Paimon ๐Ÿงช

Now ClickHouse has table functions to query Paimon tables:

SELECT * FROM paimon('s3://...');

We already support Iceberg, Delta Lake, Hudi. Why Paimon? ๐Ÿค”

— because someone uses it.

Developers: Jia Qi Tang.

Improvements for Data Lakes

Optimization for reading in table order:

If Iceberg table is already sorted, SELECT with the corresponding
ORDER BY will not require full sorting.

A log for metadata operations in Delta:

system.delta_lake_metadata_log provides information about metadata operations with Delta tables, similarly to system.iceberg_metadata_log.

Developers: Konstantin Vedernikov.

Bonus

clickgems.clickhouse.com

Meetups

— ๐Ÿ‡ช๐Ÿ‡ช Tallinn, Oct 30
— ๐Ÿ‡ธ๐Ÿ‡ช Stockholm, Nov 3
— ๐Ÿ‡จ๐Ÿ‡ด Bogota, November 13
— ๐Ÿ‡ฆ๐Ÿ‡บ LaraCon 2025, November 13
— ๐Ÿ‡ฐ๐Ÿ‡ท ClickHouse + Dev-Korea Seoul ์กฐ์ธํŠธ ๋ฐ‹์—…, November 18
— ๐Ÿ‡จ๐Ÿ‡พ Cyprus, November 20
— ๐Ÿ‡บ๐Ÿ‡ธ House Party, The SQL, Dec 2

Reading Corner ๐Ÿ“–

https://clickhouse.com/blog/

— QBit: vector search with precision at query time
— How we made the JSON data type even faster
— Achieving 170x compression of logs
— 12 frameworks for building agents with ClickHouse
— Tracing agents with ClickStack
— How to query Data Lake catalogs in the Cloud
— Netflix, GitLab, Laravel

Q&A