ClickHouse 26.5 版本发布说明
本文字数:14647;估计阅读时间:37分钟
作者:ClickHouse Team
又一个月过去了,也就意味着又到了发布新版本的时候!
ClickHouse 26.5 版本包含 38 个新功能 🌹 51 项性能优化 (performance optimizations) 🦋 224 个错误修复 🐞
本次版本带来了创纪录数量的性能优化,重点包括在连接 (joins) 中下推 ORDER BY … LIMIT (最高可提升 20× 性能)、新增 GROUP BY … LIMIT 快捷执行路径以避免构建不必要的分组、新增 filesystem 表函数,可直接对本地文件系统运行 SQL,等等!
特别欢迎 26.5 版本中的所有新贡献者!ClickHouse 社区的持续壮大令人深受鼓舞,我们也始终感谢大家的贡献,正是这些贡献让 ClickHouse 如此受欢迎。
以下是新贡献者名单:
Abhinav Agarwal, Ahaan, Alex Kuleshov, Ashrith Bandla, Asish Kumar, Callum C, Felix Bernhard, Flavio Malavazi, Ian Rakhmatullin, Ilya Perstenev, JackFielding, Joe Redfern, Larry Snizek, Luc Leray, Rahul Nair, Roy Sindre Norangshol, Venkata Vineel, Vincent Voyer, Yue, Yue Ni, functioncrafter, ibrahim karimeddin, mohaidoss, perst20, peter15914, sayondeep, zhangzhibiao, zxuhan7
由 Alexey Milovidov 贡献
“我们会在每个版本中持续优化 ClickHouse,而且会投入更多优化工作,优化永无止境”——Alexey Milovidov 在 ClickHouse 26.5 发布网络研讨会期间
把更多计算提前到 JOIN 之前
在最近几个版本中,ClickHouse 一直在稳步把更多计算提前到连接 (joins) 之前执行,从而减少需要流经 JOIN 的数据量。例如,ClickHouse 已经可以在 JOIN 查询中下推复杂的 OR 条件 (OR conditions),让每张表在执行连接之前更早完成过滤。它还支持运行时过滤器 (runtime filters):这类过滤器会基于连接右侧 (right-hand side) 生成,并在连接执行前应用到左侧 (left-hand side)。
本次发布延续了这一优化思路,但这次下推的是另一类操作:不是 WHERE 谓词 (WHERE predicate),而是 ORDER BY … LIMIT 子句 (clause)。这是一种在分析型工作负载 (analytical workloads) 中经常出现的查询模式。
从“先 JOIN 再 LIMIT”到“先 LIMIT 再 JOIN”
如果一个 LEFT JOIN 查询最外层的 SELECT 以 ORDER BY … LIMIT 结尾,并且排序键 (sort key) 只依赖左表中的列 (columns),ClickHouse 就可以把这个 ORDER BY … LIMIT 下推到 JOIN 之前执行。
当排序键只依赖右表中的列时,同样的优化也适用于 RIGHT JOIN 查询。
例如,下面这个运行在 TPC-H 表上的查询,会找出最近的 100 个订单,并补充对应的客户信息:
SELECTo_orderkey,o_orderdate,o_totalprice,c_name,c_mktsegmentFROM ordersLEFT JOIN customer ON o_custkey = c_custkeyORDER BYo_orderdate DESC,o_orderkey DESCLIMIT 100;
在这里,ORDER BY 只使用 orders 表中的列,而 orders 是 LEFT JOIN 中需要保留的一侧 (preserved side)。这意味着 ClickHouse 不必先把每个订单都和对应客户连接起来,再应用 LIMIT。
如果没有这项优化,执行计划 (plan) 就必须先执行代价高昂的 JOIN:
有了新的优化后,ClickHouse 可以反过来安排执行顺序:先从 orders 中找出前 100 行,然后只将这少量结果行与 customer 表进行 JOIN。
你也可以通过 EXPLAIN 生成的查询计划 (query plan) 看到这一变化。启用该优化后,执行计划会显示:在 orders 表一侧、与 customer 表执行 JOIN 之前,先执行 Limit 和 Sorting 步骤:
Join...LimitSortingReadFromMergeTree (sf100.orders)...ReadFromMergeTree (sf100.customer)
另一个额外好处是,ClickHouse 已经把下推后的 ORDER BY … LIMIT 当作一种原生支持的核心查询模式 (first-class query pattern) 来处理。正如我们在专门介绍 Top-N 优化的文章中提到的,ClickHouse 已经在引擎层为这种模式实现了多项优化 (engine-level optimizations)。
该优化由新的 query_plan_top_k_through_join 设置控制,并且默认启用。
基准测试:速度提升 20×,内存减少 175×
为了评估这项优化的影响,我们在一台 AWS EC2 m6i.8xlarge 实例上创建并加载了 TPC-H schema,并将缩放因子 (scale factor) 设为 100。该实例配置为 32 个 vCPU 和 128 GiB RAM。
首先,我们将 query_plan_top_k_through_join 设置为 0,禁用新的 ORDER BY … LIMIT 下推。查询共执行三次,并选取最快的一次作为基线 (baseline):
Elapsed: 2.153 sec. Processed 165.00 million rows, 3.23 GB (76.65 million rows/s., 1.50 GB/s.)Peak memory usage: 1.87 GiB.Elapsed: 1.878 sec. Processed 165.00 million rows, 3.23 GB (87.87 million rows/s., 1.72 GB/s.)Peak memory usage: 1.88 GiB.Elapsed: 2.197 sec. Processed 165.00 million rows, 3.23 GB (75.10 million rows/s., 1.47 GB/s.)Peak memory usage: 1.87 GiB.
然后,我们将 query_plan_top_k_through_join 设置为 1,启用该优化后运行同一个查询:
Elapsed: 0.093 sec. Processed 165.22 million rows, 2.18 GB (1.78 billion rows/s., 23.45 GB/s.)Peak memory usage: 11.46 MiB.Elapsed: 0.092 sec. Processed 165.22 million rows, 2.18 GB (1.80 billion rows/s., 23.70 GB/s.)Peak memory usage: 13.72 MiB.Elapsed: 0.092 sec. Processed 165.22 million rows, 2.18 GB (1.79 billion rows/s., 23.53 GB/s.)Peak memory usage: 10.98 MiB.
对比两种配置下各自最快的一次运行结果,可以看到差异非常明显:
设置 | 最快运行时间 | 峰值内存 | 读取数据 |
禁用下推 | 1.878 秒 | 1.88 GiB | 3.23 GB |
启用下推 | 0.092 秒 | 10.98 MiB | 2.18 GB |
提升 | 快 20.4× | 内存减少约 175× | 数据读取量减少 1.5× |
这个基准测试已经展示出 20.4× 的运行时间提升,同时峰值内存使用量降低了约 175×。
这些结果并不是固定上限。实际收益取决于输入表的大小、JOIN 后行的宽度、所选择的列,以及 LIMIT 的取值。
由 Amos Bird 贡献
将 Top-N 优化扩展到 GROUP BY
ClickHouse 已经把 Top-N 查询视为一种原生支持的核心查询模式。正如我们在专门介绍 Top-N 优化的文章中提到的,对于带有 ORDER BY … LIMIT 的查询,ClickHouse 已经在引擎层实现了多项优化,包括流式执行 (streaming execution)、按顺序读取 (read-in-order)、惰性读取 (lazy reading),以及基于数据跳过 (data-skipping-based) 的 Top-N 剪枝 (pruning)。
本次发布将同样的思路扩展到了另一类查询形态:没有 ORDER BY 的 GROUP BY … LIMIT 查询。
设想这样一个查询:它先按某个键分组,然后应用 LIMIT,但不包含 ORDER BY、HAVING 子句,也不包含窗口函数 (window function)。在这种情况下,查询并不需要返回最小的键、最大的键、出现频率最高的键,或者按某种特定顺序排列的键。它只需要返回任意 N 个不同的分组键。
例如,由于我们已经在上一节的基准测试中加载了 TPC-H 数据集,这里可以直接复用。下面这个查询会从 lineitem 表中返回任意 100 个不同的订单键:
SELECT l_orderkeyFROM lineitemGROUP BY l_orderkeyLIMIT 100;
从“先完成全部分组,再执行 LIMIT”到“只保留 N 个分组”
在 TPC-H 缩放因子为 100 时,lineitem 包含 6 亿行数据,以及 1.5 亿个不同的 l_orderkey 值。
如果没有这项新优化,ClickHouse 会像处理普通 GROUP BY 一样执行该查询:扫描输入数据时,每遇到一个新的 l_orderkey,就会在聚合哈希表 (aggregation hash table) 中新增一个条目。只有在聚合结果全部构建完成之后,LIMIT 100 才会把输出结果缩减到 100 行。
在本次发布中,ClickHouse 可以识别这种特殊查询模式,并避免构建那些不会影响最终结果的分组。该优化由新的 optimize_trivial_group_by_limit_query 设置控制,并且默认启用。
对于符合条件的查询,ClickHouse 会在内部将聚合限制设置为 LIMIT + OFFSET,并使用 group_by_overflow_mode = 'any'。实际执行时,这意味着一旦聚合哈希表中已经包含前 100 个不同的 l_orderkey 值,后续出现的新键就会被忽略,而不会继续作为新的分组加入。
扫描过程仍然会处理输入数据,但主内存中的聚合状态会保持得非常小:只需要保留 100 个分组,而不会增长到接近 1.5 亿个分组。
基准测试:速度提升 11.9×,内存减少 185×
为了评估这项优化的影响,我们再次在一台 AWS EC2 m6i.8xlarge 实例上运行该查询,该实例配置为 32 个 vCPU 和 128 GiB RAM。首先,我们将 optimize_trivial_group_by_limit_query 设置为 0 来禁用优化,并选择三次运行中最快的一次作为基线:
Elapsed: 0.853 sec. Processed 600.04 million rows, 2.40 GB (703.29 million rows/s., 2.81 GB/s.)Peak memory usage: 8.60 GiB.Elapsed: 0.806 sec. Processed 600.04 million rows, 2.40 GB (744.07 million rows/s., 2.98 GB/s.)Peak memory usage: 8.58 GiB.Elapsed: 0.809 sec. Processed 600.04 million rows, 2.40 GB (742.06 million rows/s., 2.97 GB/s.)Peak memory usage: 8.57 GiB.
然后,我们将 optimize_trivial_group_by_limit_query 设置为 1,启用优化后运行同一个查询:
Elapsed: 0.069 sec. Processed 600.04 million rows, 2.40 GB (8.76 billion rows/s., 35.03 GB/s.)Peak memory usage: 47.54 MiB.Elapsed: 0.070 sec. Processed 600.04 million rows, 2.40 GB (8.54 billion rows/s., 34.16 GB/s.)Peak memory usage: 47.54 MiB.Elapsed: 0.068 sec. Processed 600.04 million rows, 2.40 GB (8.79 billion rows/s., 35.17 GB/s.)Peak memory usage: 47.55 MiB.
对比两种配置下各自最快的一次运行结果:
设置 | 最快运行时间 | 处理行数 | 读取数据 | |
禁用优化 | 0.806 秒 | 6.0004 亿 | 2.40 GB | 8.58 GiB |
启用优化 | 0.068 秒 | 6.0004 亿 | 2.40 GB | 47.55 MiB |
提升 | 快 11.9× | 相同 | 相同 | 内存减少约 185× |
优化后的查询速度提升了 11.9×,峰值内存使用量也减少了约 185×。
由 Ilya Perstenev, Ilya Yatsishin, Alexey Milovidov 贡献
ClickHouse 25.6 还引入了 filesystem 表函数 (table function),可以将目录内容以可查询表 (queryable table) 的形式列出并进行分析。
filesystem 暴露出的完整 schema,涵盖了文件系统检查 (filesystem introspection) 中你会期待的各类信息:
DESCRIBE filesystem();┌─name──────────────┬─type───────────────────────────────────────────────┐│ path │ String ││ name │ String ││ type │ Enum8('none' = 0, 'not_found' = 1, 'regular' = 2, ⋯││ size │ Nullable(UInt64) ││ depth │ UInt16 ││ modification_time │ Nullable(DateTime64(6)) ││ is_symlink │ Bool ││ content │ Nullable(String) ││ owner_read │ Bool ││ owner_write │ Bool ││ owner_exec │ Bool ││ group_read │ Bool ││ group_write │ Bool ││ group_exec │ Bool ││ others_read │ Bool ││ others_write │ Bool ││ others_exec │ Bool ││ set_gid │ Bool ││ set_uid │ Bool ││ sticky_bit │ Bool ││ file │ String │└───────────────────┴────────────────────────────────────────────────────┘
如果我们使用 clickhouse-local 且不传入任何参数来调用它,它会列出当前目录中的文件:
SELECT path, name FROM filesystem();┌─path──────────────────────────────────────────────┬─name──────────────────────┐│ /Users/markhneedham/projects/release-posts/26.5 │ clickhouse ││ /Users/markhneedham/projects/release-posts/26.5 │ .claude │└───────────────────────────────────────────────────┴───────────────────────────┘
它能够访问的文件系统范围,与启动 ClickHouse 的用户所拥有的访问权限一致。如果通过 ClickHouse Server 调用它,则会列出 user_files 目录中的文件。
我的机器上有很多大型视频文件,而我 (更准确地说,是 Claude!) 通常需要运行一堆 Unix 命令才能找到它们。有了这个新函数,只需要下面这个查询就够了:
SELECT path, name, formatReadableSize(size), modification_timeFROM filesystem('/Users/markhneedham/projects/videos')WHERE type = 'regular' AND name LIKE '%.braw'ORDER BY size DESCLIMIT 3FORMAT Vertical;
Row 1:──────path: /Users/markhneedham/projects/videos/20260212-Samplename: A001_10150625_C183 2.brawformatReadableSize(size): 26.75 GiBmodification_time: 2025-10-15 06:25:08.529999Row 2:──────path: /Users/markhneedham/projects/videos/20260217-AsyncInsertsname: A001_09290151_C176.brawformatReadableSize(size): 21.70 GiBmodification_time: 2025-09-29 01:51:47.820000Row 3:──────path: /Users/markhneedham/projects/videos/20260123-PGCHStackname: A001_08021314_C119.brawformatReadableSize(size): 21.54 GiBmodification_time: 2025-08-02 13:14:33.260000
我还把这个查询封装成了一个 Claude 可以使用的技能 (skill),让它能够更快地找出可以删除的文件,从而释放磁盘空间。
由 Alexey Milovidov 贡献
如果你经常使用 url 表函数,可能已经重复输入过几十次相同的基础 URL。新的 url_base 设置可以让你只设置一次基础 URL,后续都使用相对路径 (relative paths)。
在处理 Amazon 客户评论数据集 (Amazon customer review dataset) 时,我们可以像这样设置基础 URL:
SET url_base = 'https://datasets-documentation.s3.eu-west-3.amazonaws.com/amazon_reviews/';然后可以像这样查询 2014 年的评论:
SELECTcount(),round(avg(star_rating), 2) AS stars,round(avg(helpful_votes), 2) AS votesFROM url('amazon_reviews_2014.snappy.parquet')
┌──count()─┬─stars─┬─votes─┐│ 44127569 │ 4.23 │ 0.96 │└──────────┴───────┴───────┘
如果想查询 2015 年的数据:
SELECTcount(),round(avg(star_rating), 2) AS stars,round(avg(helpful_votes), 2) AS votesFROM url('amazon_reviews_2015.snappy.parquet')
┌──count()─┬─stars─┬─votes─┐│ 41905631 │ 4.25 │ 0.74 │└──────────┴───────┴───────┘
由 Nihal Z. Miaji 贡献
26.5 版本还新增了负 LIMIT BY,它允许我们从每个分组的末尾选取行,而不是从开头选取。
我们用我最喜欢的英国房价数据集来演示它的用法。首先看下面这个查询,它会找出所有名称中包含 Yorkshire 的郡,并计算其中各个 district 的中位房价:
SELECT county, district, median(price)FROM uk_price_paidWHERE county ILIKE '%Yorkshire%'GROUP BY ALLORDER BY median(price) DESC;
┌─county───────────────────┬─district─────────────────┬─median(price)─┐│ NORTH YORKSHIRE │ NORTH YORKSHIRE │ 263000 ││ NORTH YORKSHIRE │ HARROGATE │ 185000 ││ NORTH YORKSHIRE │ HAMBLETON │ 170000 ││ NORTH YORKSHIRE │ RYEDALE │ 160000 ││ NORTH YORKSHIRE │ RICHMONDSHIRE │ 150000 ││ NORTH YORKSHIRE │ CRAVEN │ 149250 ││ NORTH YORKSHIRE │ SELBY │ 144995 ││ EAST RIDING OF YORKSHIRE │ EAST RIDING OF YORKSHIRE │ 132000 ││ WEST YORKSHIRE │ LEEDS │ 129997 ││ NORTH YORKSHIRE │ SCARBOROUGH │ 120000 ││ SOUTH YORKSHIRE │ SHEFFIELD │ 115000 ││ WEST YORKSHIRE │ KIRKLEES │ 114950 ││ WEST YORKSHIRE │ WAKEFIELD │ 112997.5 ││ SOUTH YORKSHIRE │ ROTHERHAM │ 102500 ││ WEST YORKSHIRE │ CALDERDALE │ 101000 ││ WEST YORKSHIRE │ BRADFORD │ 100000 ││ SOUTH YORKSHIRE │ DONCASTER │ 98500 ││ SOUTH YORKSHIRE │ BARNSLEY │ 95000 ││ WEST YORKSHIRE │ EAST YORKSHIRE │ 94950 │└──────────────────────────┴──────────────────────────┴───────────────┘
此前,我们已经可以选择每个郡分组中的前两行,也就是每个郡中位房价最高的两个 district:
SELECT county, district, median(price)FROM uk_price_paidWHERE county ILIKE '%Yorkshire%'GROUP BY ALLORDER BY median(price) DESCLIMIT 2 BY county
┌─county───────────────────┬─district─────────────────┬─median(price)─┐│ NORTH YORKSHIRE │ NORTH YORKSHIRE │ 262000 ││ NORTH YORKSHIRE │ HARROGATE │ 185000 ││ EAST RIDING OF YORKSHIRE │ EAST RIDING OF YORKSHIRE │ 130972.5 ││ WEST YORKSHIRE │ LEEDS │ 130000 ││ WEST YORKSHIRE │ KIRKLEES │ 115000 ││ SOUTH YORKSHIRE │ SHEFFIELD │ 115000 ││ SOUTH YORKSHIRE │ ROTHERHAM │ 105000 │└──────────────────────────┴──────────────────────────┴───────────────┘
而借助负 LIMIT BY,我们现在也可以选择每个郡分组中的最后两行,也就是每个郡中位房价最低的两个 district。
SELECT county, district, median(price)FROM uk_price_paidWHERE county ILIKE '%Yorkshire%'GROUP BY ALLORDER BY median(price) DESCLIMIT -2 BY county;
┌─county───────────────────┬─district─────────────────┬─median(price)─┐│ NORTH YORKSHIRE │ SELBY │ 145000 ││ EAST RIDING OF YORKSHIRE │ EAST RIDING OF YORKSHIRE │ 132500 ││ NORTH YORKSHIRE │ SCARBOROUGH │ 122000 ││ SOUTH YORKSHIRE │ DONCASTER │ 99000 ││ WEST YORKSHIRE │ BRADFORD │ 97500 ││ SOUTH YORKSHIRE │ BARNSLEY │ 94950 ││ WEST YORKSHIRE │ EAST YORKSHIRE │ 94950 │└──────────────────────────┴──────────────────────────┴───────────────┘
由 Kevinyhzou, Alexey Milovidov 贡献
使用 JSON_VALUE 和 JSON_QUERY 函数时,现在可以传入由多个路径 (paths) 组成的元组 (tuple) 或数组 (array),并返回对应的字符串元组或数组,而且整个 JSON 只需解析一次。
接下来我们会使用一个表示 Open House conference 信息的 JSON 字符串,并通过新的 prettyPrintJSON 函数将其打印出来:
WITH '{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27", "2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O''Farrell St, San Francisco, CA 94108"}}' AS confSELECT prettyPrintJSON(conf)FORMAT Raw;
{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27","2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O'Farrell St, San Francisco, CA 94108"}}1 row in set. Elapsed: 0.003 sec.
如果要返回字符串,例如想返回一个包含名称和场地的元组,可以使用 JSON_VALUE 函数:
WITH '{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27", "2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O''Farrell St, San Francisco, CA 94108"}}' AS confSELECT JSON_VALUE(conf, ('$.name', '$.venue.name'));
┌─JSON_VALUE(conf, ('$.name', '$.venue.name'))─┐│ ('Open House 2026','Convene 100 Stockton') │└──────────────────────────────────────────────┘
我们也可以将 JSON 路径以数组而不是元组的形式传入:
WITH '{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27", "2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O''Farrell St, San Francisco, CA 94108"}}' AS confSELECT JSON_VALUE(conf, ['$.name', '$.venue.name']);
┌─JSON_VALUE(conf, ['$.name', '$.venue.name'])─┐│ ['Open House 2026','Convene 100 Stockton'] │└──────────────────────────────────────────────┘
不过 dates.conference 是一个数组,所以如果尝试用 JSON_VALUE 获取它,会返回一个空字符串:
WITH '{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27", "2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O''Farrell St, San Francisco, CA 94108"}}' AS confSELECT JSON_VALUE(conf, ('$.name', '$.dates.conference'));
┌─JSON_VALUE(c⋯nference'))─┐│ ('Open House 2026','') │└──────────────────────────┘
我们可以使用从零开始的数组索引 (zero-based array indexing),从该数组中读取其中的单个值:
WITH '{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27", "2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O''Farrell St, San Francisco, CA 94108"}}' AS confSELECT JSON_VALUE(conf, ('$.dates.conference[0]', '$.dates.conference[1]'));
┌─JSON_VALUE(co⋯ference[1]'))─┐│ ('2026-05-27','2026-05-28') │└─────────────────────────────┘
或者,如果想将日期作为数组返回,同时返回完整的场地对象,则应该改用 JSON_QUERY:
WITH '{"name": "Open House 2026","tagline": "The real-time database for AI conference","dates": {"workshops": "2026-05-26","conference": ["2026-05-27", "2026-05-28"]},"venue": {"name": "Convene 100 Stockton","address": "40 O''Farrell St, San Francisco, CA 94108"}}' AS confSELECT JSON_QUERY(conf, ('$.dates.conference', '$.venue'))FORMAT Raw;
下面是为便于阅读而格式化后的输出:
('[["2026-05-27","2026-05-28"]]','[{"name":"Convene 100 Stockton","address":"40 O\'Farrell St, San Francisco, CA 94108"}]')
请注意,JSON_QUERY 总是会把结果包装在 [] 中,因此如果结果本身是数组值,就会出现双重包装 (double-wrapped)。
由 Alexey Milovidov 贡献
26.5 版本还引入了一个实验性的、可在浏览器中运行的 clickhouse-client (in-browser clickhouse-client)。你可以通过在配置文件中添加以下内容来启用它:
config.d/webterminal.yaml
allow_experimental_webterminal: true然后访问 http://localhost:8123/webterminal,页面中会显示类似下面的界面:
由 Nikita Barannik, Vincent Voyer 贡献
现在可以以子查询 (subquery) 为粒度控制查询缓存 (query caching)。
此前,我们已经可以通过 use_query_cache 设置,为最外层查询启用查询缓存,如下所示:
SELECT * FROM (SELECT * FROM table)SETTINGS use_query_cache = 1;
如果想为某个子查询启用查询缓存,从 26.5 开始,可以把这个设置作为后缀 (suffix) 追加到子查询后面:
SELECT *FROM (SELECT *FROM tableSETTINGS use_query_cache = 1);
我们也可以使用 use_query_cache_for_subqueries 设置,让查询缓存设置自动传递到所有子查询中:
SELECT * FROM (SELECT * FROM table)SETTINGS use_query_cache_for_subqueries = 1;
或者,也可以让查询缓存设置传递到所有子查询中,但在其中一个子查询里单独禁用查询缓存:
SELECT *FROM (SELECT * FROM table1) t1NATURAL JOIN (SELECT * FROM table2 SETTINGS use_query_cache = 0) t2SETTINGS use_query_cache_for_subqueries = 1;
/END/
试用阿里云 ClickHouse企业版
轻松节省30%云资源成本?阿里云数据库ClickHouse 云原生架构全新升级,首次购买ClickHouse企业版计算和存储资源组合,首月消费不超过99.58元(包含最大16CCU+450G OSS用量)了解详情:https://t.aliyun.com/Kz5Z0q9G
征稿启示
面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:[email protected]