首页 > 其他分享 >如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事

如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事

时间:2023-09-18 19:36:08浏览次数:51  
标签:队列 算子 查询 任务 ETL ByteHouse ELT

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群


前言

当涉及到企业分析场景时,所使用的数据通常源自多样的业务数据,这些数据系统大多采用以行为主的存储结构,比如支付交易记录、用户购买行为、传感器报警等。在数仓及分析领域,海量数据则主要采按列的方式储存。因此,将数据从行级转换成列级存储是建立企业数仓的基础能力。

传统方式是采用 Extract-Transform-Load (ETL)来将业务数据转换为适合数仓的数据模型,然而,这依赖于独立于数仓外的 ETL 系统,因而维护成本较高。但随着云计算时代的到来,云数据仓库具备更强扩展性和计算能力,也要求改变传统的 ELT 流程。

火山引擎 ByteHouse 是一款基于开源 ClickHouse 推出的云原生数据仓库,为用户提供极速分析体验,能够支撑实时数据分析和海量数据离线分析,同时还具备便捷的弹性扩缩容能力,极致分析性能和丰富的企业级特性。凭借其强大的计算能力,可以全面支持 Extract-Load-Transform (ELT)的能力,从而使用户免于维护多套异构系统。

具体而言,用户可以将数据导入后,通过自定义的 SQL 语句,在 ByteHouse 内部进行数据转换,而无需依赖独立的 ETL 系统及资源。这样,用户只需要采用统一的 SQL 方式来完成数据转换操作。

在本文中,我们将重点介绍 ByteHouse 遇到的挑战,以及如何通过 3 大能力建设实现完备的 ELT 能力。


痛点以及挑战

我们先从一个简单的 SSB(start-schema-benchmark)场景出发, 其中包含:

  • 1 个事实表: lineorder
  • 4 个维度表:customer, part, supplier, dwdate

如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事_大数据

在 SSB 的查询分析中,我们发现大部分的查询都涉及到事实表和维表的 join,因此可以通过 Transform 的步骤,将事实表“打平”。 打平所用到的 SQL 如下:

insert into ssb_flat 
select * from
lineorder l
join customer c on l.lo_custkey = c.c_custkey
join part p on l.lo_partkey = p.p_partkey
join supplier s on l.lo_suppkey = s.s_suppkey
where l.lo_orderdate = <bizdate>

之后的查询分析可以通过对ssb_flat 的单表扫描来规避很多join操作,其性能能有显著提升。 这个“打平”的过程,就是“Transform”的一种。 实际生产场景中的“Transform”的 case 会更多也更复杂。 但是通过以上这个“打平”的过程,我们可以分析出这类操作在数据库上的普遍性痛点。


变换操作跟普通查询相比,有几个大的区别:

  1. 变换操作执行时间久, 整体重试成本高
  2. 变换操作没有返回值,我们只关心他成功或者失败
  3. 变化操作读写量大,占用资源


具体来说:

  • 首先对于 ByteHouse 来讲,其擅长的临时查询时间都在秒级,查询中间出故障一般都直接返回错误,交由上游重试。而在 ETL 场景下,一个任务如果执行了 50 分钟,由于某些原因故障了,重试相当于前 50 分钟的资源都被浪费了,显然不能被接受。
  • 其次,由于 ETL 没有返回结果,客户端需要保持一个 idle 的长链接,很有可能由于配置原因超时,同时大量的并发任务也会吃掉正常的链接资源。
  • 最后,由于 ETL 任务读写量大,多个任务并发的时候,需要考虑到资源的分配,以达到性能和隔离的平衡。

针对这三个痛点,ByteHouse 针对性的设计了三个功能,即长任务管理、异步提交和查询队列。


功能一:长任务管理

通常情况下,我们可以用 settings max_execution_time 来控制一个查询的超时时间,ByteHouse 提供了事务支持来保障读写操作的原子性。

但是并这不足以覆盖 ETL 任务的需求。 在长时间的任务执行中,更容易遇到系统性故障,如节点 OOM 等。在这种情况下,由客户端重试并不是个优雅的方案。

在 ByteHouse 中,一个 SQL 查询会被转化为一系列的算子。 我们希望提升算子的容错能力以更好的应对长时间查询下的系统故障。目前的版本中,ByteHouse 已经针对聚合,排序,关联等算子提供了 disk spill 功能。 具体来说,当某个算子无法获得足够的内存时,我们允许这个算子将一部分数据缓存在磁盘上,以此在资源紧张的情况下仍能够完成工作。

例如在排序算子中,我们引入了 external merge sort 的能力,并通过max_bytes_before_external_sort来控制外部排序能力。在下图左边是未开启 spill 的排序查询计划,右边是开启 spill 的计划。

如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事_云原生_02


如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事_火山引擎_03

可以看到在开启 external sort 之后,ByteHouse 引入了 BufferingToFileTransform,MergingSortedTransform 两个算子。同样的,ByteHouse 里的聚合,关联算子都做了类似的优化例如 grace hash join 等。

接下来 ByteHouse 也打算针对 exchange 操作,进一步提升 shuffle 操作的容错性。


功能二:异步提交能力

面对大量长耗时的 ETL 任务时,传统的同步执行的方式需要客户端等待服务端返回。 这样很容易出现客户端超时,进而影响后续任务执行的问题。

同时,在这种场景中,用户并不关心单个任务或请求的相应时间,只期望任务能在特定时间内完成,并对可靠性等要求较高。 因此 ByteHouse 提供了异步提交的任务的能力。

ByteHouse 用户现在可以通过 setting enable_async_execution 来提交一个异步任务。ByteHouse 在收到这类任务之后,会返回一个异步任务 ID, 例如 ff46fccf-d872-4c68-bdb2-c8c18fc178f5。 之后客户端可以选择间歇性轮训来获得任务的最终状态。

ByteHouse 提供了 show async status 'ff46fccf-d872-4c68-bdb2-c8c18fc178f5' 的指令来获得状态。 同时 ByteHouse 也提供了 kill query 'ff46fccf-d872-4c68-bdb2-c8c18fc178f5'的指令来取消某些异步的查询。


功能三:查询队列

离线加工面对大量请求时,当系统超载,需要一定的排队机制使 query 请求挂起,等待集群释放资源后再进行调度。ByteHouse 为此提供了查询队列能力。

ByteHouse 可以允许用户从三个维度度来定义一个队列,即: 队列大小,总 CPU 占用率,和总内存占用率。

在 ByteHouse 中,Resource Manager 组件可以用来监听各个队列中的查询指标,得到队列的资源使用率。 当用户向一个队列提交查询时,如果队列还未达到上限,ByteHouse 会将这个查询入队,否则拒绝掉这个查询。

此后,ByteHouse 会时刻检查队列的资源利用率,当空闲资源高过某个阀值时,Bytehouse 会将等待中的查询出队。当某个处于等待期的查询被取消时,ByteHouse 也会将其移出队列。利用查询队列,用户在编排 ETL 任务时不用担心底层资源过载,因此可以更加自由。

之后 ByteHouse 也在计划增加优先级队列功能。届时,用户可以为 ETL 任务和即时查询创建不同队列优先级,这样 ELT 任务和即时查询可以跑在同一个计算组中而不会显著的相互影响。


总结

以上介绍了 ByteHouse 在支持 ETL 能力中的一些技术细节。其中长任务,异步提交已经队列功能已经在 preview 版本中上线。接下来,ByteHouse 也会继续扩展 ETL 能力,包括支持更多的 ETL 相关的转换函数、长任务容错、优先级队列等。

除了 ELT 能力之外,火山引擎 ByteHouse 基于独家自研的高可用引擎及查询优化器,可以为企业提供快速、稳定、安全的查询服务和数据写入性能。在云原生架构下,火山引擎 ByteHouse 提供了极致扩展的统一数据分析平台,具有出色的弹性伸缩和可扩展性,确保资源可以灵活地水平扩展;

同时,ByteHouse 支持多级资源隔离,为用户资源提供更安心的安全保障。火山引擎 ByteHouse 还从业务角度出发提供了完整的运维监控和排障能力,帮助企业实现业务云上托管,降低运维成本。欢迎登陆火山引擎 ByteHouse 官网体验。


点击跳转 云原生数据仓库ByteHouse 了解更多

标签:队列,算子,查询,任务,ETL,ByteHouse,ELT
From: https://blog.51cto.com/bytedata/7514379

相关文章

  • 如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 前言当涉及到企业分析场景时,所使用的数据通常源自多样的业务数据,这些数据系统大多采用以行为主的存储结构,比如支付交易记录、用户购买行为、传感器报警等。在数仓及分析领域,海量数据则主......
  • Deltix Round, Autumn 2021 (open for everyone, rated, Div. 1 + Div. 2) A. Divide
    有一个长为\(n\)的数组,可以执行以下整份操作任意次:选择任意两个数\(a_i,a_j\),满足\(2\mida_i\)\(a_i=\frac{a_i}{2}\)\(a_j=2\cdota_j\)请找到经过任意此操作后的最大\(\sum_{i=1}^{n}a_i\)。在唯一分解定理下讨论两个数\(a_i=2^{\alpha_i}\cdotx,a......
  • 最高提升10倍性能!揭秘火山引擎ByteHouse查询优化器实现方案
     更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 作为企业级数据库的核心组件之一,查询优化器的地位不可忽视。对于众多依赖数据分析的现代企业来说,一个强大且完善的查询优化器能够为数据管理和分析工作带来巨大的便利。 作为火山引......
  • 火山引擎 ByteHouse:两个关键技术,揭秘 OLAP 引擎中的数据导入技术
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群数据导入是衡量OLAP引擎性能及易用性的重要标准之一,高效的数据导入能力能够加速数据实时处理和分析的效率。作为一款OLAP引擎,火山引擎云原生数据仓库ByteHouse源于开源ClickHouse,在字节跳......
  • 火山引擎 ByteHouse:两个关键技术,揭秘 OLAP 引擎中的数据导入技术
     更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 数据导入是衡量OLAP引擎性能及易用性的重要标准之一,高效的数据导入能力能够加速数据实时处理和分析的效率。 作为一款OLAP引擎,火山引擎云原生数据仓库ByteHouse源于开源C......
  • 如何实现数据流畅转换?火山引擎ByteHouse推出ELT能力
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群在数据分析场景中,企业使用的数据通常具备来源多样化的特点,如支付交易记录、用户行为等,且数据格式各异,有的为行式存储结构,有的为列式存储结构。这就要求企业数仓具备一定的数据转换能力。传统方式......
  • OperationError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection':
    webRTC报“OperationError:Failedtoexecute'setLocalDescription'on'RTCPeerConnection':Failedtosetlocaloffersdp:Calledinwrongstate:have-remote-offer”异常 翻译过来的意思不应该have-remote-offer状态去设置setLocalDescription。定位到错误的地方,我是......
  • CDC一键入湖:当 Apache Hudi DeltaStreamer 遇见 Serverless Spark
    ApacheHudi的DeltaStreamer是一种以近实时方式摄取数据并写入Hudi表的工具类,它简化了流式数据入湖并存储为Hudi表的操作,自0.10.0版开始,Hudi又在DeltaStreamer的基础上增加了基于Debezium的CDC数据处理能力,这使得其可以直接将Debezium采集的CDC数据落地成Hudi表,这一功能极大地简......
  • ELT已死,EtLT才是现代数据处理架构的终点!
    提到数据处理,经常有人把它简称为“ETL”。但仔细说来,数据处理经历了ETL、ELT、XXETL(例如,ReverseETL、Zero-ETL)到现在流行的EtLT架构几次更迭。目前大家使用大数据Hadoop时代,主要都是ELT方式,也就是加载到Hadoop里进行处理,但是实时数据仓库、数据湖的流行,这个ELT已经过时了,EtLT才......
  • getline的几种用法
    istream库下istream&getline(char*s,streamsizen);istream&getline(char*s,streamsizen,chardelim);从istream输入流中读取字符传入字符串s,个数为n string库下istream&getline(istream&is,string&str,chardelim);istream&getline(istre......