ClickHouse SQL 格式化工具
粘贴一段 ClickHouse 查询,立刻得到格式化结果。本工具使用真正的 ClickHouse 语法,而不是用 MySQL 近似,因此 ClickHouse 特有的语法能完整保留;它还会读取 {name:Type} 查询参数,让你填好值后直接得到一条可执行的查询。
一条 ClickHouse 查询,格式化前后对比
下面这条未格式化的查询就是上方编辑器里加载的示例,输出则是本工具在默认选项下返回的原始结果,没有任何手工修饰。
WITH matched AS (SELECT fingerprint FROM traces_resource WHERE simpleJSONExtractString(labels, 'service.name') = {service:String}), ranked AS (SELECT resource_string_service$$name AS svc, toStartOfInterval(timestamp, INTERVAL 60 SECOND) AS ts, attributes_string['http.method'] AS method, quantile(0.95)(duration_nano) AS p95 FROM signoz_index_v3 PREWHERE timestamp >= {start_ts:UInt64} AND timestamp <= {end_ts:UInt64} WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM matched) GROUP BY svc, ts, method) SELECT * FROM ranked WHERE p95 > {threshold:UInt64} ORDER BY ts DESC SETTINGS max_threads = 8 WITH
matched AS (
SELECT
fingerprint
FROM
traces_resource
WHERE
simpleJSONExtractString(labels, 'service.name') = {service:String}
),
ranked AS (
SELECT
resource_string_service$$name AS svc,
toStartOfInterval(timestamp, INTERVAL 60 SECOND) AS ts,
attributes_string['http.method'] AS method,
quantile(0.95)(duration_nano) AS p95
FROM
signoz_index_v3
PREWHERE
timestamp >= {start_ts:UInt64}
AND timestamp <= {end_ts:UInt64}
WHERE
resource_fingerprint GLOBAL IN (
SELECT
fingerprint
FROM
matched
)
GROUP BY
svc,
ts,
method
)
SELECT
*
FROM
ranked
WHERE
p95 > {threshold:UInt64}
ORDER BY
ts DESC
SETTINGS
max_threads = 8 它能处理的 ClickHouse 语法
通用格式化工具往往会破坏方言特有的语法,或者干脆拒绝处理。以下是本工具针对 ClickHouse 做过测试的语法结构。
{name:Type} ClickHouse 的查询参数被识别为真正的参数,并以参数名而非类型来命名。填一次 start_ts,所有用到的地方都会更新;DateTime64、Array 和 Nullable 类型会映射到合适的输入控件。
PREWHERE 作为与 WHERE 并列的、可独立编辑的过滤子句被识别出来,让你可以调整真正决定 ClickHouse 读取路径的那一段。
ARRAY JOIN 保持为单个子句,而不会被拆成一个并不存在的 JOIN。
attributes['key'] map 和数组下标会被原样保留,包括 attributes_string['http.method'] 这类带点号的键。
quantile(0.95)(x) 参数化聚合函数的两个参数列表会紧挨着保持在一起。
column$$name 包含 $$ 的物化列被当作标识符处理,而不是未闭合的美元引用字符串。
GLOBAL IN 分布式查询运算符原样保留,其内部的子查询仍然可编辑。
SETTINGS / FORMAT 结尾处的子句会被识别为子句边界,因此编辑 WHERE 时绝不会把它们吞掉。
ClickHouse 格式化工具常见问题
它能理解 ClickHouse 的查询参数吗?
可以。ClickHouse 的 {name:Type} 参数会被检测出来、按名称分组,并依据声明的类型定型。类型相同的两个参数——比如 {start_ts:UInt64} 和 {end_ts:UInt64}——仍然彼此独立,填写其中一个不会覆盖另一个。把输出切换为填值 SQL,就能得到一条可以直接执行的查询。
它能格式化由多个 CTE 构成的查询吗?
可以,而且还能编辑它们。查询中的每个 WHERE 和 PREWHERE 子句都会按所属的 CTE 列出,你可以挑一个,用 AND/OR 树或节点图来编辑。改动会被精确拼回那一个子句,查询的其他部分不会移动。
我的 ClickHouse 查询会被发送到服务器吗?
不会。格式化完全在你的浏览器中进行,因此生产查询、表名和内嵌的值都不会离开你的机器。
为什么编辑 WHERE 子句不会把末尾的 SETTINGS 一起吞掉?
因为 SETTINGS 和 FORMAT 是按参数语法识别的,而不是只看关键字本身。这个区分在两个方向上都有效:过滤一个恰好叫 settings 的列时,查询仍能正确解析;而末尾的 SETTINGS max_threads = 8 会被识别为子句边界,不会被卷进你正在编辑的条件里。
支持 ARRAY JOIN 和 map 类型的列吗?
支持。ARRAY JOIN 会保持为单个子句,不会被拆成并不存在的 JOIN;map 下标也原样保留,包括 attributes_string['http.method'] 这类带点的键——简单的格式化工具会在点号两侧插入空格,把它破坏掉。
能处理名字里带两个美元符号的物化列吗?
可以。像 resource_string_service$$name 这样的名字会被当作标识符,而不是 Postgres 风格美元引用字符串的开头。这里判断错了会把查询余下的部分整体清空,之后的所有参数和 WHERE 子句都会悄悄消失——把 SigNoz 或可观测性相关的表结构粘进通用格式化工具时,遇到的正是这个问题。