ClickHouse: Release 26.6 Call

Author: Alexey Milovidov, 2026-06-25.

ClickHouse Release 26.6

ClickHouse release 26.6

1. (50 min) What's new in ClickHouse 26.6.

2. (10 min) Q&A.

Release 26.6

ClickHouse "10 Year Anniversary" Release.

โ€” 56 new features ๐ŸŒž

โ€” 79 performance optimizations ๐Ÿ–๏ธ

โ€” 366 bug fixes ๐Ÿฆ

Small And Nice Features

ALTER TABLE โ€ฆ ADD ENUM VALUES

Append new Enum values without re-typing all the existing ones:

CREATE TABLE events (x Enum8('a' = 1, 'b' = 2)) ...; -- Before: ALTER ... MODIFY COLUMN x Enum8('a'=1,'b'=2,'c'=3,'d'=4) ALTER TABLE events MODIFY COLUMN x ADD ENUM VALUES('c' = 3, 'd' = 4); -- x is now Enum8('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4)

โ€” A pure metadata change โ€” instant, no data rewrite.
โ€” Forgetting an existing value is no longer possible.

Developer: Ilya Golshtein.

Number formatting controls

Precision arguments and decimal-point control for text output:

SELECT formatReadableSize(1234567890, 4); -- 1.1498 GiB (default precision is 2: 1.15 GiB) SELECT 1/3 SETTINGS output_format_float_precision = 4; -- 0.3333 SELECT 5.0 SETTINGS output_format_always_write_decimal_pointโ€ฆ = 1; -- 5. (keep the decimal point even for whole numbers)

โ€” formatReadableSize / formatReadableQuantity / formatReadableDecimalSize take an optional precision.

Developers: Antonio Filipovic, phulv94, Ilya Yatsishin.

Cascading refreshable materialized views

A refreshable MV can now trigger off another RMV's refresh:

CREATE MATERIALIZED VIEW base REFRESH EVERY 1 HOUR ENGINE = MergeTree ORDER BY day AS โ€ฆ; CREATE MATERIALIZED VIEW rollup REFRESH DEPENDS ON base ENGINE = โ€ฆ AS SELECT day, sum(x) FROM base GROUP BY day;

Developer: Michael Kolupaev.

Control over projection materialization

Two new MergeTree settings decouple projection building from INSERT:

CREATE TABLE ... SETTINGS materialize_projections_on_insert = 0; -- INSERTs skip building projection parts โ†’ faster ingestion CREATE TABLE ... SETTINGS materialize_projections_on_merge = 1; -- a merge rebuilds a projection missing from all its source parts

โ€” Tables with many projections ingest faster;
โ€ƒ projections are built during merges instead.

Developer: Christoph Wurm.

IP-prefix quotas

Key a quota by a subnet, not just a single address:

CREATE QUOTA q KEYED BY ip_address IPV4_PREFIX_BITS 24 FOR INTERVAL 1 hour MAX queries = 1000; -- every client in a /24 shares one quota bucket CREATE QUOTA q6 KEYED BY ip_address IPV6_PREFIX_BITS 64 โ€ฆ;

โ€” Rate-limit a whole network range at once.
โ€” Works with IP_ADDRESS and FORWARDED_IP_ADDRESS keys.
โ€” Especially useful for IPv6.

Developer: Aditya Chopra.

Usability

help in the CLI

Type help <name> in clickhouse-client / clickhouse-local to read the docs
right in the terminal โ€” backed by system.documentation:

:) help MergeTree

โ€” Also /help, man, /man. Resolves ambiguity and typos.
โ€” Markdown rendered in the terminal, with syntax-highlighted SQL.

Demo

Developer: Alexey Milovidov.

Docs embedded in every system table

System tables that describe the system now describe themselves โ€” with
description, syntax, examples, introduced_in and related columns:

SELECT name, introduced_in FROM system.table_engines WHERE name ILIKE '%kafka%'; SELECT name, description FROM system.data_type_families;

Now self-documenting: table_engines, database_engines, data_type_families, formats, aggregate_function_combinators, dictionary_layouts, dictionary_sources, data_skipping_index_types, disk_types.

Developer: Alexey Milovidov.

system.documentation

The whole reference manual, as a table, inside the server:

SELECT type, count() FROM system.documentation GROUP BY type;

typecount
Function1592
Setting1548
Server Setting / MergeTree Setting412 / 316
Aggregate Function, Data Type, Format, โ€ฆโ€ฆ

โ€” The same docs as the website โ€” queryable, greppable, offline.
โ€” Good for integration with tools.

Developer: Alexey Milovidov.

New system tables

More of ClickHouse, introspectable as tables:

SELECT table, name, type, expression FROM system.constraints;

โ€” system.constraints โ€” every table's CHECK / ASSUME constraints.
โ€” system.iceberg_files โ€” introspection of files in Iceberg tables.

Keeper related tables (available on clickhouse-keeper):
โ€” system.keeper_snapshots
โ€” system.keeper_changelogs
โ€” system.keeper_cluster.

Developers: Pedro Ferreira, Miัhael Stetsyuk, Han Fei.

Which AI agent is querying you?

ClickHouse now detects the AI coding agent that launched the client,
from its environment, and records it in a new client_agent column:

SELECT query_id, client_agent, interface FROM system.processes;

query_idclient_agentinterface
ai_democlaude-code1

โ€” Recognizes Claude Code, Cursor, Codex, Gemini CLI, Goose, โ€ฆ
โ€” Also in system.query_log and system.query_thread_log.

Developer: Alexey Milovidov.

Transform clickhouse-local to a server

clickhouse-local can now start listening for connections on the fly:

clickhouse-local :) SYSTEM START LISTEN TCP; :) SYSTEM START LISTEN HTTP; -- now other clients can connect to your local session

โ€” Turn an ad-hoc analysis session into a shareable endpoint.
โ€” SYSTEM STOP LISTEN to close it again.

Developer: Alexey Milovidov.

Schema Visualizer

A new built-in web UI that draws the dependency graph of your database:

http://localhost:8123/schema

โ€” Tables, materialized views, refreshable MVs, dictionaries,
โ€ƒ distributed tables and views โ€” and the arrows between them.
โ€” See at a glance how data flows from ingestion to rollups.
โ€” Embedded in the server.

Developer: Nikita Mikhaylov.

PNG output format

Render query results as an image. One row per pixel (r, g, b or v),
with implicit or explicitly defined pixel coordinates (x, y):

WITH number DIV 1024 AS y, number MOD 1024 AS x, L2Norm((x - 512, y - 512)) / 512 AS radius, 60 AS stripe_size, round((atan2(x - 512, y - 512) / pi() * 180 + exp(radius) * 90) / stripe_size) * stripe_size AS alpha, radius <= 1 ? abs(1 - (radius - 0.5) * (radius - 0.5) * 4) : 0 AS a, colorOKLCHToSRGB((0.7, 0.15, alpha)) AS rgb SELECT rgb.1::UInt8 AS r, rgb.2::UInt8 AS g, rgb.3::UInt8 AS b, a FROM numbers(1048576) FORMAT PNG SETTINGS output_format_image_terminal_mode = 'kitty'

โ€” The Web UI shows the image directly.
โ€” Great for heatmaps, sparklines, generated art.

Developer: Maksim Dergousov.

SQL Compatibility

date_part and EXTRACT

date_part('unit', expr)
โ€” PostgreSQL-style sugar for EXTRACT(unit FROM expr):

SELECT date_part('year', toDateTime('2026-06-25 10:30:00')); -- 2026 SELECT date_part('doy', toDate('2026-06-25')); -- 176 (day of year) SELECT date_part('dow', toDate('2026-06-25')); -- 4 (day of week)

โ€” All the PostgreSQL extras: epoch, dow, doy, isodow, isoyear, century, decade, millennium.
โ€” Also: EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE FROM dt)
โ€ƒ and EXTRACT(โ€ฆ FROM INTERVAL n โ€ฆ).

Developers: Alexey Milovidov, Vinayak Joshi.

Miscellaneous functions and names

More SQL-standard / PostgreSQL spellings:

SELECT LOCALTIMESTAMP; -- now() โ†’ DateTime SELECT LOCALTIME; -- current time of day โ†’ Time SELECT SESSION_USER; -- alias of currentUser()

โ€” No parentheses needed โ€” they are reserved-word constants.
โ€” Makes more ported queries and BI-tool SQL just work.

Developers: Thomas Cabral, Takumi Hara.

More compatibility aliases

min_by / max_by โ€” aliases for argMin, argMax for PostgreSQL, BigQuery:

SELECT min_by(user, score), max_by(user, score) FROM t; -- aliases of argMin / argMax

REGEXP_SUBSTR โ€” alias of regexpExtract, for Oracle/MySQL/Snowflake:

SELECT REGEXP_SUBSTR('order 12345 shipped', '[0-9]+'); -- 12345

"These aliases are stupid, real engineers use the original ClickHouse names." โ€” the changelog

ALTER TABLE MODIFY COLUMN x UInt32 NULL; -- same as Nullable(UInt32)

Developers: Joey Yu, Alexey Milovidov, Takumi Hara.

SOME / ALL for arrays

PostgreSQL array quantifiers with a literal array on the right:

SELECT 3 = SOME([1, 2, 3]); -- 1 โ†’ rewritten to has(...) SELECT 5 > ALL([1, 2, 3]); -- 1 โ†’ arrayAll lambda SELECT 2 <> ALL([1, 3, 5]); -- 1

The subquery form of ANY / SOME / ALL still lowers to IN / NOT IN.

Developer: Alexey Milovidov.

Select columns by name pattern

Pick columns with * LIKE and * ILIKE instead of listing them:

SELECT * ILIKE '%user%' FROM events; -- user_id, user_name, ... (case-insensitive) SELECT t.* ILIKE '%id', count() FROM t GROUP BY ALL; -- qualified form works too

Similar to * MATCH 'regexp' and COLUMNS('regexp'),
but with SQL-style LIKE patterns instead of a regular expression.

Developer: Yue Ni.

ESCAPE in LIKE

Define a custom escape character so % and _ can be literal:

SELECT '50% off' LIKE '50!% off' ESCAPE '!'; -- 1 (the !% matches a literal percent sign) SELECT 'a_b' LIKE 'a!_b' ESCAPE '!'; -- 1 (the !_ matches a literal underscore)

โ€” SQL-standard syntax, also accepted by PostgreSQL, MySQL, โ€ฆ

Developer: Ilya Yatsishin.

Geospatial

GeoJSON input format

Read a GeoJSON FeatureCollection โ€” one row per feature:

SELECT id, properties.name, toTypeName(geometry) FROM file('places.geojson', GeoJSON);

idproperties.namegeometry
1LondonGeometry (Point)
2squareGeometry (Polygon)

โ€” Columns: id String, geometry Geometry, properties Nullable(JSON).
โ€” Point, LineString, MultiLineString, Polygon, MultiPolygon supported natively.

Developer: Mark Needham.

Mapbox Vector Tiles from SQL

Serve map tiles straight out of ClickHouse with the new MVT functions:

-- Project lon/lat into a tile's pixel space: SELECT MVTEncodeGeom((13.37, 52.52)::Point, 10, 550, 335); -- (124, 3384) -- Aggregate a group's geometries into one binary tile: SELECT MVTEncode(geom_in_tile_space) FROM ...; -- Tile bounding box for the WHERE clause: SELECT MVTBoundingBox(12, 1205, 2557);

โ€” Point, line and polygon geometry.
โ€” Also available as PostGIS aliases ST_AsMVTGeom and ST_AsMVT.

Developer: Saarthak Gupta.

Performance Improvements

ClickHouse Keeper is 2x faster

A round of Keeper improvements makes it more twice as fast overall:

โ€” Better request batching.
โ€” Pipelining messages to the leader.
โ€” Pipelining log appends.
โ€” Snapshot I/O moved to a background thread (nuraft_use_bg_thread_for_snapshot_io).
โ€” Lower peak memory when applying received snapshots.

On a realistic workload with keeper-bench:

26.5: 2899 RPS, 41.4 ms latency
26.6: 7230 RPS, 18.3 ms latency

Developers: Michael Kolupaev, Antonio Andelic, Mikhail Filimonov.

Lighter, faster query startup

Per-query overhead for simple queries is significantly reduced:

SELECT count() FROM hits; -- parsing + analysis + planning ~50% faster from a single connection

More analysis wins, all enabled by default:

โ€” Identifier-resolution caching during analysis.
โ€” Fast analysis of deeply nested subqueries.
โ€” Faster resolution for deeply nested function calls.
โ€” Faster processing of changing access control entities.

Deeply nested SELECT * over a 1200-column table:
โ€ƒ analysis 1.46 s โ†’ 0.023 s  (~64x), 26.5 vs 26.6.

Developers: Raรบl Marรญn, Dmitry Novik, Max Justus Spransy, Azat Khuzhin.

Primary key analysis is faster

Long or high-cardinality primary keys used to make index analysis slow.

Now (use_lightweight_primary_key_index_analysis, on by default):

โ€” For a long primary key, analysis time depends on the columns the query
โ€ƒ actually filters on โ€” not on the length of the key.
โ€ƒ Extending the sorting key is now nearly free for index analysis.

โ€” For a high-cardinality key, analysis works on just the selective
โ€ƒ in-memory prefix instead of loading the whole key.

Developer: Nihal Z. Miaji.

Faster sorting

The general-purpose comparison sorts are now C++ ports
of ipnsort and driftsort:

โ€” Faster ORDER BY on non-numeric columns and for stable sorts.
โ€” Removes a worst case on already reverse-sorted input.
โ€” State-of-the-art, adaptive, and battle-tested algorithms.

ORDER BY 20M strings, single thread:
โ€ƒ 7.1 s โ†’ 5.9 s  (~1.2x), 26.5 vs 26.6.

Developer: Alexey Milovidov.

Faster GROUP BY and JOIN

โ€” Sharded aggregation for high-cardinality, evenly-distributed keys
โ€ƒ (enable_sharding_aggregator = 1): hash the key to scatter rows across
โ€ƒ threads, so each thread aggregates a disjoint subset โ€” no merge phase.
โ€” Hash-table prefetching for string-key GROUP BY: ~8% faster.
โ€” Lower peak memory when merging large two-level aggregation states
โ€ƒ (e.g. groupArray).
โ€” More optimal handling of Nullable columns in aggregation.
โ€” Packed keys32 / keys64 methods in HashJoin and Set.

Measured โ€” 300M-row high-cardinality GROUP BY, 16 threads:
โ€ƒ enable_sharding_aggregator: 2.31 s โ†’ 1.87 s.

Developers: Nihal Z. Miaji, Le Zhang, Yuri Fedoseev, Nikita Taranov.

LIMIT BY, optimized many ways

A whole family of new optimizations for LIMIT BY (all on by default):

โ€” Run LIMIT BY inside each parallel sorted stream during ORDER BY
โ€ƒ when its keys are a prefix of the sort key.
โ€” Stream LIMIT N BY cols in primary-key order with O(1) memory per stream.
โ€” Apply LIMIT BY per partition in parallel when the partition is a
โ€ƒ function of the keys.
โ€” Drop redundant / injective key expressions
โ€ƒ (LIMIT 5 BY toString(x) โ†’ LIMIT 5 BY x).

Measured โ€” LIMIT 3 BY g over a 50M-row MergeTree (g is in the sort key):
โ€ƒ memory 86 MiB โ†’ 22 MiB (~4x), time 0.15 s โ†’ 0.09 s.

Developer: Nihal Z. Miaji.

JOIN optimizations

A batch of JOIN planner and runtime improvements, mostly on by default:

โ€” enable_join_transitive_predicates on by default โ€” push derived
โ€ƒ predicates across the join (filter both sides for free).
โ€” Build-side FixedHashMap doubles as the probe-side runtime filter.
โ€” Lazy selector / replication indexes when a JOIN is followed by a
โ€ƒ selective LIMIT / TopN / another JOIN.
โ€” parallel_hash is now allowed for ASOF JOIN.
โ€” Packed keys32 / keys64 in HashJoin; fast path for single-row probes.
โ€” Dynamic Programming join reordering now works with parallel replicas.

Developers: A. Gololobov, N. Taranov, H. Selmi, Xiaozhe Yu, G. Maher.

Something Interesting

Continuous queries ๐Ÿงช

A SELECT that never ends โ€” the first step toward streaming queries. Append STREAM and it keeps emitting new rows as they are inserted:

SET enable_streaming_queries = 1; SELECT id, msg FROM live_events STREAM; -- blocks, keeps streaming

Applications: filtering and real-time alerting on a stream of events.

Advanced usage with cursors:

SELECT _block_number AS bn, _block_offset AS bo, id, msg FROM events STREAM CURSOR {'all': {'block_number': 2, 'block_offset': 0}}

Developer: Mikhail Artemenko.

Multi-stage distributed query execution ๐Ÿงช

The experimental distributed planner splits a query plan into stages
connected by exchanges โ€” and ships fragments to worker nodes:

โ€” scatter / broadcast / gather / shuffle exchanges.
โ€” Distributed shuffle and broadcast hash joins, shuffle aggregation, distributed sort.
โ€” Data between stages streamed over TCP or temp files in object storage.
โ€” Several workers per host (stateless_worker_port / streaming_exchange_port).

Controlled by a new setting, make_distributed_plan.

Developer: Alexander Gololobov.

Memory reservations for workloads

The workload scheduler โ€” which already manages CPU, I/O and concurrency โ€” now manages memory too:

CREATE RESOURCE memory (MEMORY RESERVATION); CREATE WORKLOAD all; CREATE WORKLOAD prod IN all SETTINGS max_memory = '100G'; CREATE WORKLOAD reports IN all SETTINGS max_memory = '20G'; CREATE WORKLOAD vasya IN reports SETTINGS weight = 1; CREATE WORKLOAD petya IN reports SETTINGS weight = 2; -- route a query to a workload: SELECT โ€ฆ SETTINGS workload = 'prod'; -- reserve memory before processing: SET reserve_memory = '5G';

Developer: Sergei Trifonov.

Hypothetical indexes + EXPLAIN WHATIF

Ask "what if I had this skip index?" โ€” without building it:

CREATE HYPOTHETICAL INDEX idx_level ON logs (level) TYPE set(2) GRANULARITY 4; EXPLAIN WHATIF SELECT count() FROM logs WHERE level = 'error';

Baseline (PK + partition + existing indexes): marks: 612, 19.56 MiB With idx_level (set, hypothetical): status: applicable marks: 200 (was 612) est_bytes: 6.39 MiB skip_ratio: 67.3% Estimation: empirical, sampled 5/5 parts

โ€” Session-scoped, visible in system.hypothetical_indexes.
Tune indexes data-driven.

Developer: Yarik Briukhovetskyi.

aiEmbed ๐Ÿงช

Generate text embeddings from inside ClickHouse, via an LLM API:

SELECT aiEmbed('qwen3-8b', review_text) AS embedding FROM reviews LIMIT 10; -- Array(Float32) per row, ready for cosineDistance / vector search

โ€” Build a semantic-search or RAG pipeline without leaving SQL.
โ€” Pairs with the new quantization functions for compact vector indexes.
โ€” Experimental โ€” configure your embedding provider and model.

Developer: George Larionov.

Quantization functions

A scalar codec that compresses embedding components to 8bit and below:

SELECT quantizeBFloat16ToInt8(1.5::BFloat16); -- 107 SELECT dequantizeInt8ToBFloat16(quantizeBFloat16ToInt8(1.5::BFloat16)); -- 1.5 (near-lossless round-trip)

โ€” 256-level Gaussian Lloydโ€“Max quantizer; one byte per component.
โ€” Int4 / Int2 / binary codes fall out by bit-truncation โ€” trade size for recall.
โ€” Shrinks vector indexes 4x (or more) for cheaper similarity search.

Developer: Alexey Milovidov.

Bonus

https://clickhouse.com/benchmarks/costbench

Meetups


โ€” ๐Ÿ‡ฆ๐Ÿ‡บ Sydney: Agentic AI Unplugged, Jun 24
โ€” ๐Ÿ‡บ๐Ÿ‡ธ Seattle Iceberg Meetup, Jun 25
โ€” ๐Ÿ‡ฒ๐Ÿ‡พ Kuala Lumpur Meetup, Jun 26
โ€” ๐Ÿ‡ฐ๐Ÿ‡ท Seoul: ClickHouse + Confluent, Jun 30
โ€” ๐Ÿ‡บ๐Ÿ‡ธ San Francisco: AI Demo Night, Jul 1
โ€” ๐Ÿ‡ฎ๐Ÿ‡ณ Mumbai: Lakes to Queries, Jul 4
โ€” ๐Ÿ‡บ๐Ÿ‡ธ New York: AI Builders Night, Jul 8
โ€” ๐Ÿ‡ฉ๐Ÿ‡ช Berlin: WeAreDevelopers, Jul 8
โ€” ๐Ÿ‡จ๐Ÿ‡ฆ Montreal: OSS Happy Hour, Jul 9
โ€” ๐Ÿ‡ฎ๐Ÿ‡ณ Bangalore: Fast Data at Scale, Jul 11
โ€” ๐Ÿ‡ฆ๐Ÿ‡บ Melbourne Meetup, Jul 16
โ€” ๐Ÿ‡ฏ๐Ÿ‡ต Tokyo: Google Cloud Next, Jul 30

Reading Corner ๐Ÿ“–

QR: clickhouse.com/blog/open-source-10

https://clickhouse.com/blog/

โ€” Ten years of open source
โ€” How ClickHouse became fast at joins
โ€” Integrating the Rust Delta Kernel into ClickHouse
โ€” Introducing multi-stage distributed query execution
โ€” CostBench: an open benchmark for data warehouse cost-performance
โ€” TPC-H for less than a cent: ClickHouse Cloud
โ€ƒ vs. Snowflake, Databricks, BigQuery, and Redshift
โ€” The end-to-end cost-performance: Snowflake vs. ClickHouse Cloud
โ€” The future of observability: thousands of agents, not one proprietary AI

Q&A