ClickHouse 25.12 版本如期而至,带来了26项新特性、31项性能优化和129个bug修复。作为一款生产级分析型数据库管理系统,ClickHouse在ClickBench和JSONBench等基准测试中持续保持领先地位。本文将深入剖析该版本的核心改进,帮助开发者更好地理解和使用这些新功能。
Top-N查询是数据分析中最常见的模式之一,在ClickBench基准测试中占比超过50%。ClickHouse 25.12通过创新性地利用数据跳过索引,显著提升了这类查询的性能。
对于不含谓词的简单Top-N查询,如:
sql复制SELECT * FROM T ORDER BY c ASC LIMIT 3;
当列c上存在minmax数据跳过索引时,ClickHouse会执行以下优化流程:
在实际测试中,这种优化使查询速度提升了5倍,处理行数从1亿行降至16.3万行,数据读取量从1.2GB减少到4.95MB。
对于包含谓词的Top-N查询,如:
sql复制SELECT URL,EventTime FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMIT 10;
ClickHouse采用动态阈值过滤机制:
测试显示,这种优化使查询速度提升10倍,处理行数从1亿行降至700万行,数据读取量从9.42GB减少到520.58MB。
注意事项:要启用这些优化,需要设置use_skip_indexes_for_top_k=1和use_top_k_dynamic_filtering=1。同时确保相关列已创建minmax数据跳过索引。
在25.12之前,惰性读取采用逐行物化剩余列的方式。对于LIMIT 100,000的查询,这意味着要进行约100,000×104=10,400,000次独立的列查找操作,导致性能下降。
25.12版本重构了惰性读取的实现:
测试结果显示,新模型使查询速度提升75倍(相比旧惰性读取)和14倍(相比非惰性读取),处理时间从34秒降至0.5秒左右。
实操心得:query_plan_max_limit_for_lazy_materialization的默认值已从10提升到10,000。对于更大的LIMIT值,建议评估排序成本与I/O节省的平衡。
Join顺序对查询性能有决定性影响。ClickHouse 25.12引入了DPsize算法,相比原有的贪心算法能探索更多可能的join顺序。
DPsize是一种动态规划方法:
在TPC-H基准测试中,DPsize生成的执行计划比贪心算法快约4.7%。随着查询复杂度的增加,这种优势会更加明显。
使用建议:通过query_plan_optimize_join_order_algorithm='dpsize,greedy'设置启用DPsize,它会先尝试DPsize,失败时回退到贪心算法。
在25.12中,创建文本索引必须显式指定tokenizer:
sql复制CREATE TABLE hackernews (
...
INDEX inv_idx(text) TYPE text(tokenizer = 'splitByNonAlpha') GRANULARITY 128
) ORDER BY time;
可用tokenizer包括:splitByNonAlpha、splitByString、ngrams、sparseGrams和array。
使用hasToken、hasAllTokens和hasAnyTokens函数进行搜索:
sql复制-- 查找包含"OpenAI"的内容
SELECT by, count() FROM hackernews WHERE hasToken(text, 'OpenAI') GROUP BY ALL;
-- 查找同时包含"OpenAI"和"Google"的内容
SELECT by, count() FROM hackernews WHERE hasAllTokens(text, ['OpenAI', 'Google']) GROUP BY ALL;
-- 查找包含"OpenAI"或"Google"的内容
SELECT by, count() FROM hackernews WHERE hasAnyTokens(text, ['OpenAI', 'Google']) GROUP BY ALL;
注意事项:要使LIKE查询使用文本索引,需确保能提取完整token(如'% OpenAI %'而非'%OpenAI%')。
新增dictGetKeys函数可反向查询字典:
sql复制-- 创建字典
CREATE DICTIONARY taxi_zone_dictionary (...);
-- 查询Bronx区域的所有LocationID
SELECT dictGetKeys('taxi_zone_dictionary', 'Borough', 'Bronx');
该函数会自动创建缓存加速批量查找,可通过max_reverse_dictionary_lookup_cache_size_bytes控制缓存大小。
25.12支持IN子句中使用非固定列表:
sql复制SELECT dropoff_nyct2010_gid, payment_type, count()
FROM trips
WHERE dropoff_nyct2010_gid IN (payment_type = 'CSH' ? [138] : [132])
GROUP BY ALL;
新增HMAC函数用于消息认证,可实现webhook签名验证:
sql复制-- 创建接收webhook的表
CREATE TABLE webhook_staging (
received_at DateTime DEFAULT now(),
raw_payload String,
signature String DEFAULT getClientHTTPHeader('X-Hub-Signature-256')
);
-- 创建验证签名的物化视图
CREATE MATERIALIZED VIEW webhook_validator TO webhook_prod AS
SELECT ... FROM webhook_staging
WHERE signature = 'sha256=' || lower(hex(HMAC('SHA256', raw_payload, 'my_secret_key')));
配置提示:需要设置allow_get_client_http_header=1以读取HTTP头信息。
Top-N查询优化:
大结果集查询:
复杂Join优化:
全文搜索:
字典查询:
在实际生产环境升级前,建议在测试环境中充分验证这些变更对现有查询的影响,特别是性能敏感型查询。对于关键业务系统,可考虑逐步启用新特性而非一次性全部开启。