云数据库ClickHouse资源隔离 - 弹性资源队列

本文深入解析ClickHouse的MPP计算模型,探讨现有资源隔离的痛点,并详细介绍阿里云数据库ClickHouse即将推出的自研弹性资源队列功能,旨在提升资源利用率和查询稳定性。该资源队列允许内存资源抢占,动态调整并发限制,以应对分布式多表关联查询带来的挑战。
摘要由CSDN通过智能技术生成

引言

ClickHouse内核分析系列文章,本文将为大家深度解读ClickHouse当前的MPP计算模型、用户资源隔离、查询限流机制,在此基础上为大家介绍阿里巴巴云数据库ClickHouse在八月份即将推出的自研弹性资源队列功能。ClickHouse开源版本当前还没有资源队列相关的规划,自研弹性资源队列的初衷是更好地解决隔离和资源利用率的问题。下文将从ClickHouse的MPP计算模型、现有的资源隔离方案展开来看ClickHouse当前在资源隔离上的痛点,最后为大家介绍我们的自研弹性资源队列功能。

MPP计算模型

在深入到资源隔离之前,这里有必要简单介绍一下ClickHouse社区纯自研的MPP计算模型,因为ClickHouse的MPP计算模型和成熟的开源MPP计算引擎(例如:Presto、HAWQ、Impala)存在着较大的差异(que xian),这使得ClickHouse的资源隔离也有一些独特的要求,同时希望这部分内容能指导用户更好地对ClickHouse查询进行调优。

ClickHouse的MPP计算模型最大的特点是:它压根没有分布式执行计划,只能通过递归子查询和广播表来解决多表关联查询,这给分布式多表关联查询带来的问题是数据shuffle爆炸。另外ClickHouse的执行计划生成过程中,仅有一些简单的filter push down,column prune规则,完全没有join reorder能力。对用户来说就是"所写即所得"的模式,要求人人都是DBA,下面将结合简单的查询例子来介绍一下ClickHouse计算模型最大的几个原则。

递归子查询

在阅读源码的过程中,我可以感受到ClickHouse前期是一个完全受母公司Yandex搜索分析业务驱动成长起来的数据库。而搜索业务场景下的Metric分析(uv / pv ...),对分布式多表关联分析的并没有很高的需求,绝大部分业务场景都可以通过简单的数据分表分析然后聚合结果(数据建模比较简单),所以从一开始ClickHouse就注定不擅长处理复杂的分布式多表关联查询,ClickHouse的内核只是把单机(单表)分析做到了性能极致。但是任何一个业务场景下都不能完全避免分布式关联分析的需求,ClickHouse采用了一套简单的Rule来处理多表关联分析的查询。

对ClickHouse有所了解的同学应该知道ClickHouse采用的是简单的节点对等架构,同时不提供任何分布式的语义保证,ClickHouse的节点中存在着两种类型的表:本地表(真实存放数据的表引擎),分布式表(代理了多个节点上的本地表,相当于"分库分表"的Proxy)。当ClickHouse的节点收到两表的Join关联分析时,问题比较收敛,无非是以下几种情况:本地表 Join 分布式表 、本地表 Join 本地表、 分布式表 Join 分布式表、分布式表 Join 本地表,这四种情况会如何执行这里先放一下,等下一小节再介绍。

接下来问题复杂化,如何解决多个Join的关联查询?ClickHouse采用递归子查询来解决这个问题,如下面的简单例子所示ClickHouse会自动把多个Join的关联查询改写成子查询进行嵌套, 规则非常简单:1)Join的左右表必须是本地表、分布式表或者子查询;2)倾向把Join的左侧变成子查询;3)从最后一个Join开始递归改写成子查询;4)对Join order不做任何改动;5)可以自动根据where条件改写Cross Join到Inner Join。下面是两个具体的例子帮助大家理解:

例1

select * from local_tabA 
join (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1
on local_tabA.key1 = sub_Q1.key1
join dist_tabD on local_tabA.key1 = dist_tabD.key1;
=============>
select * from 
(select * from local_tabA join 
 (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1
on local_tabA.key1 = sub_Q1.key1) as sub_Q2
join dist_tabD on sub_Q2.key1 = dist_tabD.key1;

例2

select * from local_tabA 
join (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1
on local_tabA.key1 = sub_Q1.key1
join dist_tabD on local_tabA.key1 = dist_tabD.key1;
=============>
select * from 
(select * from local_tabA join 
 (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1
on local_tabA.key1 = sub_Q1.key1) as sub_Q2
join dist_tabD on sub_Q2.key1 = dist_tabD.key1;

Join关联中的子查询在计算引擎里就相关于是一个本地的"临时表",只不过这个临时表的Input Stream对

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值