记一次clickhouse查询问题Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = ‘deny‘)

最近在工作中使用到了clickhouse,在查询数据统计的时候遇到了一点问题,后来解决了,记录一下

ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统–DBMS ( 来自不同列的值被单独存储,来自同一列的数据被存储在一起 )

适用于大多数是读请求,数据较少更新或者没有更新的场景。clickhouse的一大优点是支持SQL, 在查询的学习成本上低于es.

SQL格式如下:

[WITH expr_list|(subquery)]
SELECT [DISTINCT] expr_list
[FROM [db.]table | (subquery) | table_function] [FINAL]
[SAMPLE sample_coeff]
[ARRAY JOIN ...]
[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN (subquery)|table (ON <expr_list>)|(USING <column_list>)
[PREWHERE expr]
[WHERE expr]
[GROUP BY expr_list] [WITH TOTALS]
[HAVING expr]
[ORDER BY expr_list] [WITH FILL] [FROM expr] [TO expr] [STEP expr]
[LIMIT [offset_value, ]n BY columns]
[LIMIT [n, ]m] [WITH TIES]
[UNION ALL ...]
[INTO OUTFILE filename]
[FORMAT format]

业务场景:
一批数据周期调用某个接口,每次调用的结果都会记录下来,想按照周期来统计该数据的调用结果。
每个周期内数据的唯一id是businessId,在同一周期内相同businessId的数据保留最新的一条作为统计数据源

SQL:对指定周期内的数据,统计其最新的business信息

SELECT * FROM db.t_data t1 inner join 
(SELECT businessId , max(lastchangetime) lasttime FROM db.t_data where
lastchangetime >= toDateTime('?') and lastchangetime <= toDateTime('?')  
and businessId >= ? and businessId <=? group by businessId) t2 
on t1.businessId = t2.businessId and t1.lastchangetime = t2.lasttime

这个sql在MySQL执行是OK的,但是在clickhouse执行会报如下错误:"syntax error, expect {, actual error, pos 1, line 1, column 2Code: 288, e.displayText() = DB::Exception: Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = 'deny'). You may rewrite query to use local tables in subqueries, or use GLOBAL keyword, or set distributed_product_mode to suitable value. (version 20.1.4.14 (official build))\n"

根据报错信息,因为不支持分布式子查询而发生如上报错,建议是在子查询里使用本地表或者使用GLOBAL, 我将inner join 改为global join 就没有报错了

那么clickhouse的分布式查询又是怎么一回事呢?

带子查询的IN-s有两个选项(类似于连接):normal IN / JOIN 和 GLOBAL IN / GLOBAL JOIN. 它们在分布式查询处理的运行方式上有所不同。

当使用常规IN时,查询被发送到远程服务器,并且它们中的每个服务器都在运行子查询 IN 或JOIN 条款

使用 GLOBAL IN / GLOBAL JOINs时,首先所有的子查询都运行 GLOBAL IN / GLOBAL
JOINs,并将结果收集在临时表中。 然后将临时表发送到每个远程服务器,其中使用此临时数据运行查询。

分布式子查询主要是用于在连接查询时,如果关联的数据分散在不同的集群中,那么子查询就需要先在所有集群节点上查询,然后以其并集作为子查询的结果集,否则查询出来的结果不准确。为了提高效率,官方是推荐使用global join(将 GLOBAL 修饰的子句,单独进行了一次分布式查询, 子查询的结果合并后存储在临时表中)代替普通的join。

参考资料:
ClickHouse概述
ClickHouse分布式IN & JOIN 查询的避坑指南
house.tech/docs/zh/sql-reference/operators/in/

猜你喜欢

转载自blog.csdn.net/qq_35448165/article/details/110682206