ClickHouse从分布式表的子查询中报表不存在问题看分布式表查询流程

ClickHouse从分布式表的子查询中报表不存在问题看分布式表查询流程

背景

有SQL如下执行报错(其中default.zkm表是分布式表,default.notdistribute表是普通的MergeTree引擎表):

CK01 :) select * from default.zkm where id in (select id from default.notdistribute);
...省略部分内容...
Received exception from server (version 22.3.2):
Code: 60. DB::Exception: Received from localhost:9000. DB::Exception: Received from dev-app77:9000. DB::Exception: Table default.notdistribute doesn't exist. (UNKNOWN_TABLE)

构造并说明

CREATE TABLE default.zkm_local ON CLUSTER zkm
(
    `id` String DEFAULT 'NULL' COMMENT '用户编号',
    `repo` String DEFAULT 'NULL' COMMENT '仓库编号'
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/zkm-{shard}/default/zkm_local', '{replica}')
ORDER BY id;

CREATE TABLE default.zkm ON CLUSTER zkm
(
    `id` String DEFAULT 'NULL' COMMENT '用户编号',
    `repo` String DEFAULT 'NULL' COMMENT '仓库编号'
)
ENGINE = Distributed('zkm', 'default', 'zkm_local', hiveHash(id));

--default.notdistribute只有dev-app76(CK01)有。
CREATE TABLE default.notdistribute ( `id` String DEFAULT 'NULL' COMMENT '用户编号', `repo` String DEFAULT 'NULL' COMMENT '仓库编号' ) ENGINE = MergeTree ORDER BY id;

集群是一个两分片的架构:

CK01 :) select * from system.clusters where cluster='zkm';

SELECT *
FROM system.clusters
WHERE cluster = 'zkm'

Query id: fc714b11-ef24-4200-947c-b92afaf6563f

┌─cluster─┬─shard_num─┬─shard_weight─┬─replica_num─┬─host_name─┬─host_address──┬─port─┬─is_local─┬─user────┬─default_database─┬─errors_count─┬─slowdowns_count─┬─estimated_recovery_time─┐
│ zkm     │         1 │            1 │           1 │ dev-app76 │ 192.168.1.171 │ 9000 │        1 │ default │                  │            0 │               0 │                       0 │
│ zkm     │         2 │            1 │           1 │ dev-app77 │ 192.168.1.172 │ 9000 │        0 │ default │                  │            0 │               0 │                       0 │
└─────────┴───────────┴──────────────┴─────────────┴───────────┴───────────────┴──────┴──────────┴─────────┴──────────────────┴──────────────┴─────────────────┴─────────────────────────┘

2 rows in set. Elapsed: 0.004 sec. 

注意到在dev-app76(CK01)上执行报错SQL,错误信息是“Received from dev-app77:9000. DB::Exception: Table default.notdistribute doesn't exist.“。

dev-app77是集群中的另外个节点,这说明dev-app76的SQL被分解到dev-app77的SQL中也含有default.notdistribute表,所以报表不存在。

分布式查询和分布式子查询原理根据官网:中文 英文 或者《ClickHouse原理解析与应用实践》的P245-P250可知:

分布式查询SELECT * FROM default.zkm在请求节点被执行后会被转化为SELECT * FROM zkm_local后在发送到其他远端分片节点来执行,最终多个分片数据返回后在请求节点合并处理。

同样的,有分布式子查询如下:

SELECT id FROM zkm WHERE id in (SELECT ID FROM zkm_local);

该SQL会被分解为:

SELECT id FROM zkm_local WHERE id in (SELECT ID FROM local_table);

PS:在分布式子查询中这种分解原理可能会导致查询结果不准确(详见上边提到的官档或书籍),因此常用global in代替in解决此问题,不过gobal in也有需要注意的地方,不展开讲。

因此,回到一开始的SQL:

select * from default.zkm where id in (select id from default.notdistribute);

该SQL被分解为:

select * from default.zkm_local where id in (select id from default.notdistribute);

然后跑到dev-app77上边去执行,因此报表不存在。

解决方法

将SQL改为如下后可解决此问题:

select * from default.zkm where id global in (select id from default.notdistribute);

global in的原理不同于in,大致分为3个过程:

  1. 将IN子句单独拿出,由请求者服务器将运行子查询
  2. 结果将被放在RAM中的临时内存表中。 然后请求将被发送到每个远程服务器
  3. 将外层分布式表转为本地表后开始执行完成的SQL语句,IN子句直接使用临时内存表的数据

若子查询单独拿出后的SQL也是分布式查询,则按照分布式查询原理分解执行。

至此。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ClickHouse是一个高性能列式数据库系统,特别适合大数据分析和在线事务处理(OLAP)场景。在ClickHouse,数据可以存储在本地分布式,它们各自有不同的特点和应用场景。 **1. 本地(Local Table):** - **定义:** 本地是存储在单个节点(或副本集的某个节点)上的数据结构,适合较小的数据集或对实时查询有较高要求的情况。 - **优点:** 查询速度快,因为数据是按照列存储的,并且可以直接从磁盘读取,减少了网络延迟。 - **缺点:** 随着数据量的增长,扩展性有限,如果需要更大的存储容量或更高的并发访问,需要手动复制到其他节点或使用分布式。 **2. 分布式(Distributed Table):** - **定义:** 分布式是由多个本地组成,数据分布在多台服务器上,每个部分存储一部分数据。这样可以提供更好的水平扩展和容错能力。 - **优点:** 可以处理大量数据,支持并行查询,提高了处理大规模数据的能力。数据分布可以根据负载均衡策略自动调整。 - **缺点:** 查询可能涉及网络I/O,速度可能会受到网络延迟的影响。此外,分布式的复杂性也意味着维护和管理可能更复杂一些。 - **创建与查询:** 创建分布式时需要指定一个分布式键(distr_id),并指定参与存储的数据源本地查询分布式时,ClickHouse会自动将查询分散到各个子,执行结果再汇总。 **相关问题--:** 1. 如何在ClickHouse创建本地? 2. 如何设置分布式的复制策略? 3. 分布式如何提高查询性能? 4. 如何进行分布式的故障恢复? 5. 分布式和并行查询有何关联?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值