Clickhouse分布式表引擎(Distributed)查询核心原理解析

news2024/11/16 7:22:20

Clickhouse分布式表引擎(Distributed)查询核心原理解析

  • Clickhouse分布式表引擎(Distributed)写入核心原理解析
  • Clickhouse分布式表引擎(Distributed)查询核心原理解析

与分布式数据写入时可以选择写分布式表或本地表有所不同,在面向集群查询数据的时候,只能通过Distributed表引擎实现。当Distributed表接收到SELECT查询的时候,它会依次查询每个分片的数据,再合并汇总返回。

多副本的路由规则

在查询数据的时候,如果集群中的一个shard,拥有多个replica,那么Distributed表引擎需要面临副本选择的问题。它会使用负载均衡算法从众多replica中选择一个,而具体使用何种负载均衡算法,则有load_balancing参数控制:

load_balancing = random/nearest_hostname/in_order/first_or_random

有如下四种负载均衡算法:

(1)random

random是默认的负载均衡算法。在Clickhouse的服务节点中,拥有一个全局计数器errors_count,当服务发生任何异常时,该计数累加1。而random算法会选择errors_count错误数量最少的replica。如果有多个replica的errors_count计数相同,则在它们之中随机选择一个。

(2)nearest_hostname

nearest_hostname可以看作random算法的变种,首选它会选择errors_count错误数量最少的replica,如果多个replica的errors_count计数相同,则选择集群配置中host名称与当前host最相似的一个。而相似的规则是以当前host名称为基准按字节逐位比较,找出不同字节数最少的一个。

例如:

CH-1-1
CH-1-2
只有一个字节不同

CH-1-1
CH-2-2
有两个字节不同

(3)in_order

in_order同样可以看作random算法的变种,首先它会选择errors_count错误数量最少的replica,如果多个replica的errors_count计数相同,则按照集群配置中的replica的定义顺序逐个选择。

(4)first_or_random

first_or_random可以看作in_order算法的变种,首先它会选择errors_count错误数量最少的replica,如果多个replica的errors_count计数相同,它首先会选择集群配置中第一个定义的replica,如果该replica不可用,则进一步随机选择一个其他的replica。

多分片查询的核心流程

分布式查询与分布式写入类似,同样本着谁执行谁负责的原则,它会由接收SELECT查询的Distributed表,并负责串联起整个过程。首先它会将针对分布式表的SQL语句,按照分片数量将查询拆分成若干个针对本地表的子查询,然后向各个分片发起查询,最后再汇总各个分片的查询结果。如果对分布式表按如下方式发起查询:

SELECT * FROM distributed_table

那么,它会将其转为如下形式之后,再发送到远端分片节点来执行:

SELECT * FROM local_table

SQL的执行计划

在这里插入图片描述

Distributed表引擎会将查询计划转换为多个分片的UNION联合查询,以此合并最终的查询结果。

整个执行计划从上至下大致分成两个步骤:

(1)查询各个分片数据

在上图所示的执行计划中,One和Remote步骤是并行执行的,它们分别负责了本地和远端分片的查询动作。其中,在One步骤会将SQL转换成对本地表的查询。在本例中,我们有一个分布式表test_shard_dist:

SELECT count() FROM test.shard_dist;

在集群中的其他节点的服务日志可以看到:

<Debug> executeQuery: (from [::ffff:192.168.80.121]:57412, initial_query_id: 822da000-3799-4ee0-8824-76cfc2db7537) SELECT count() FROM `test`.`test_shard_local`

其他节点在收到查询请求后,会将查询转换成对本地表的查询。

(2)合并返回结果

多个分片数据均查询返回后,按如下方法在发起分布式查询的节点上汇总返回结果:

<Debug> test.test_shard_local (SelectExecutor): Choose complete Aggregate projection _minmax_count_projection

使用Global优化分布式子查询

如果在分布式查询中使用子查询,可能会面临两难的局面。下面来看一个示例。假设有这样一张分布式表test_query_dist,它拥有两个分片,每个分片内的数据如下所示:

Linux121节点:

SELECT *
FROM test_query_local

Query id: 7c34fedf-64ae-4e68-b146-2931f6693a3a

┌─id─┬─repo─┐
│  1100 │
│  2100 │
│  3100 │
└────┴──────┘

3 rows in set. Elapsed: 0.004 sec. 

Linux122节点:

SELECT *
FROM test_query_local

Query id: 15932914-66d6-4e6b-a6f9-adc5b66dcb83

┌─id─┬─repo─┐
│  3200 │
│  4200 │
└────┴──────┘

2 rows in set. Elapsed: 0.002 sec. 

其中,id代表用户的编号,repo代表仓库编号。如果现在有一项查询需求,要求找到同时拥有两个仓库的用户。

对于这种交集查询的需求,可以使用IN子查询,:

select uniq(id) from test_query_dist where repo = 100
and id in (select id from test_query_dist where repo = 200);

执行查询可以发现以下报错:

Received exception from server (version 22.4.6):
Code: 288. DB::Exception: Received from localhost:9000. 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.: While processing  test_query_dist: While processing id IN (SELECT id FROM test_query_dist WHERE repo = 200). (DISTRIBUTED_IN_JOIN_SUBQUERY_DENIED)

报错信息中提示了Double-distributed IN/JOIN subqueries is denied,表示平方次的IN/JSON子查询是不允许的。这是什么问题呢?

这是由于上面的SQL语句在IN查询子句中,同样使用了分布式表查询:

select id from test_query_dist where repo = 200

所以在Linux122节点接收到这条SQL之后,它将再次向其他分片发起远程请求,如同所示:

在这里插入图片描述

因此可以得出结论,在IN查询子句使用分布式表的时候,查询请求会被放大N的平方倍,其中N等于集群内分片节点的数量,假如集群内有10个分片节点,则在一次查询的过程中,会最终导致100次的查询请求,这显示是不可接受的。这也是上面报错的原因,Clickhouse不允许使用这种方式,直接报错。

使用GLOBAL优化查询

为了解决查询放大的问题,可以使用GLOBAL IN或JSON进行优化。现在对刚才的SQL进行改造,为其增加GLOBAL修饰符:

select uniq(id) from test_query_dist where repo = 100
and id global in (select id from test_query_dist where repo = 200);

再次分析查询的核心过程,如下图所示:

在这里插入图片描述

整个过程由上至下大致分成5个步骤:

  1. 将IN子句单独踢出,发起了一次分布式查询。
  2. 将分布式表转local本地表后,分别在本地和远端分片执行查询
  3. 将IN子句查询的结果进行汇总,并放入一张临时的内存表进行保存
  4. 将内存表发送到远端分片节点
  5. 将分布式表转为本地表后,开始执行完整的SQL语句,IN子句直接使用临时内存表的数据

至此,整个核心流程结束。可以看到,在使用GLOBAL修饰符之后,CLickhouseHouse使用内存表临时保存了IN子句查询到的数据,并将其发送到远端分片节点,以此到达了数据共享的目的,从而避免了子查询放大的问题。由于数据会在网络间分发,所以需要特别注意临时表的大小,IN或者JOIN子句返回的数据不宜过大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/466827.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有哪家台灯好又便宜的适合学生党使用?真正合格的小学生台灯

都说眼睛是心灵的窗户&#xff0c;但是现在很多小朋友还没上初中&#xff0c;可能就早早的近视了。究其原因&#xff0c;除了和频繁观看电子屏幕密不可分之外&#xff0c;不良的用眼习惯也是一大关键。孩子写作业时不时揉眼睛的动作&#xff0c;其实只要时间一长&#xff0c;眼…

MYSQL prefer_order_index 的罪责

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

Linux运维之初识shell

一.补充知识点 1.系统定时任务 系统定时任务需要用到crontab命令&#xff0c;但是使用此命令有一个前提&#xff0c;即需要打开crond服务。为了不那么复杂&#xff0c;可以直接使用我之前学的systemctl命令重新启动crond服务。 语法&#xff1a;crontab [-e -l -r] 选项&am…

安装zsh-theme oh-my-zsh

安装zsh yum install zsh切换到zsh chsh -s /bin/zsh exec /bin/zsh重启并且查看 echo $SHELL//查看当前shell,如果显示/bin/zsh&#xff0c;则配置成功 安装oh my zsh sh -c "$(wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)"到…

浅谈Java线程

大家好&#xff0c;我是易安&#xff01;今天我们简单聊下Java线程这个话题。 在Java领域&#xff0c;实现并发程序的主要手段就是多线程。线程是操作系统里的一个概念&#xff0c;虽然各种不同的开发语言如Java、C#等都对其进行了封装&#xff0c;但是万变不离操作系统。Java语…

您的天气类APP会泄露隐私吗?

不知您是否有这样的习惯&#xff0c;在早上出门前、或是在规划次日的行程时&#xff0c;都会不自觉地掏出手机、点开天气类APP进行查看。此类APP有的是智能手机自带的&#xff0c;有的是从应用商店里下载并获取的第三方应用。无论是哪种&#xff0c;它们往往都有着一个共性&…

网络安全合规-汽车行业数据合规

个人信息&#xff0c;是指以电子或者其他方式记录的与已识别或者可识别的车主、驾驶人、乘车 人、车外人员等有关的各种信息&#xff0c;不包括匿名化处理后的信息。 敏感个人信息&#xff0c;是指一旦泄露或者非法使用&#xff0c;可能导致车主、驾驶人、乘车人、车外人员等受…

神策营销云时效性升级,秒级营销即刻开启

信息化时代&#xff0c;时效性成为企业营销与管理的重要竞争力之一。高时效营销能够帮助企业提高决策效率、降低成本&#xff0c;“争分夺秒”留住用户并给用户带来更好的体验&#xff0c;它是促成企业成功营销的关键。 为了帮助企业全面提升营销时效性&#xff0c;神策营销云即…

一次修改jar包中字节码文件内容的尝试

目录 背景解决办法确定修改位置得到字节码文件修改字节码文件组合jar包 背景 最近想实现按照分节符拆分doc / docx文档的功能&#xff0c;然后就找到了这篇文章Java 按节拆分 Word 文档&#xff0c;用的依赖是&#xff1a; <dependency><groupId>e-iceblue</g…

Arduno ESP8266接入OneNET实时显示DHT11数据

Arduno ESP8266接入OneNET实时显示DHT11数据 📌相关篇《OneNET云平台数据APP端查看说明》📍《Arduno ESP8266接入中移OneNet动态显示实时数据》✨上面一篇主要是验证数据上传可行性,这次采用DHT11温湿度传感器上传真实数据到云平台进行检测,同时使用SSD1306屏幕进行数据显…

简单聊聊目标检测新范式RT-DETR的骨干:HGNetv2

【前言】 本文版权属于GiantPandaCV&#xff0c;未经许可&#xff0c;请勿转账&#xff01; 前几天疯狂刷屏的RT-DETR赚足了眼球&#xff0c;在精度和速度上体现的优势和性价比远远高于YOLO&#xff0c;而今年ChatGPT、Sam的出现&#xff0c;也让一些吃瓜群众知乎CNN没有未来了…

第8章:树

1.树是什么 一种分层数据的抽象模型前端工作中常见的树包括&#xff1a;DOM树&#xff0c;级联选择(省市区)&#xff0c;树形控件&#xff0c;…javascript中没有树&#xff0c;但是可以用Object和Array构建树 4.树的常用操作&#xff1a;深度/广度优先遍历&#xff0c;先中后…

【传统方式部署zookeeper集群与迁移至k8s】

zookeeper简介&#xff1a; zk主要服务于分布式系统、配置管理、注册中心、集群管理等&#xff1b;为什么要迁移Zookeeper集群&#xff1b;存储kafka什么数据&#xff1a;kafka有多少节点、topic名称、协调kafka正常运行。ELKKafka收集k8s日志&#xff1b;一、传统方式部署zook…

浙江省区块链数字资产登记中心筹备会议顺利举行

4月25日下午&#xff0c;由浙江省区块链技术应用协会主办、西溪谷管委会、西湖区网联会协办的“浙江省区块链数字资产登记中心筹备会议”在西湖蚂蚁小镇多功能厅顺利举行。 出席本次筹备会议的有中国电子技术标准化研究院区块链研究室主任、IEEE 计算机 协会区块链和分布式记帐…

设计模式--桥接模式

传统方案解决手机操作问题分析 (1) 扩展性问题(类爆炸) 如果我们再增加手机的样式(全面屏) 就需要增加各个品牌手机的类 同样如果我们增加一个手机品牌 也要在各个手机样式类下增加 (2) 违反了单一职责原则 当我们增加手机样式时 要同时增加所有品牌的手机 增大了代码维护成本…

【STM32】基础知识 第九课 STM32启动

【STM32】基础知识 第九课 STM32启动 MAP 文件MAP 文件浅析MAP 文件组成atk_f103.map 文件 启动模式STM32 启动模式 (F1) STM32 启动过程启动文件介绍Reset_Handler 函数介绍堆栈简介 MAP 文件 MAP 文件是 MDK 编译代码后, 产生的集程序, 数据及 IO 空间的一种映射列表文件. 简…

谁是液冷行业真龙头?疯狂的液冷技术!

“人工智能领域AIGC”、“ChatGPT”、“数据特区”、“东数西算”、“数据中心”&#xff0c;可以说是2023年最热的概念&#xff0c;算力提升的背后&#xff0c;处理器的功耗越来越高&#xff0c;想发挥出处理器的最高性能&#xff0c;需要更高的散热效率。 算力井喷之下&…

Blender 建模案例一(1)

目录 1. 指环1.1 创建一个柱体1.2 柱体微调1.3 缩放1.4 应用缩放1.5 物体属性回归默认1.6 进入编辑模式1.7 内插面1.8 桥接循环边1.9 添加表面细分修改器1.10 平滑着色1.11 添加环切 2. 卷轴2.1 添加曲线2.2 进入正交前视图2.3 添加节点2.4 曲线转3D 1. 指环 1.1 创建一个柱体…

Wifi ESL方案介绍

革新点&#xff1a; 7.5寸墨水屏显示WIFI无线通信&#xff0c;极简部署&#xff0c;远程控制按键及LED指示灯指示640*384点阵屏幕锂电池供电&#xff0c;支持USB充电DIY界面支持文本/条码/二维码/图片超低功耗/超长寿命&#xff0c;一次充电可用一年基于现有Wifi环境&#xff…

APS54083 深度调光降压恒流驱动IC 8A LED摩托汽车舞台工作灯IC PWM调光 优化线路图

APS54083 是一款 PWM 工作模式,高效率、外 围简单、外置功率 MOS 管&#xff0c;适用于 5-220V 输入高精度降压 LED 恒流驱动芯片。输出最大 功率150W最大电流 6A。APS54083 可实现线 性调光和 PWM 调光&#xff0c;线性调光脚有效电压 范围 0.5-2.5V.PWM 调光频率范围 1…