与Presto和Apache Parquet在Uber进行工程数据分析

0
与Presto和Apache Parquet在Uber进行工程数据分析

从确定最方便的乘客接车点到预测最快的路线,优步使用数据驱动分析来创造无缝的出行体验。在工程领域,分析为全面的决策过程提供信息。随着我们拓展到新的市场,准确快速地汇总数据的能力变得更加重要。

2014年初,优步在全球只有几百名员工。但到2016年底,我们有超过2000人每天运行超过10万个分析查询。我们需要一个数据查询系统来跟上我们的增长。为了对多个数据源运行分析查询,我们设计了一个分析系统转眼间一个用于大型数据集的开源分布式SQL引擎,以及拼花是Hadoop的一种柱状存储格式。

在本文中,我们概述了我们的Presto架构,并讨论了我们如何开发一个新的Parquet读取器来支持Uber的rob科大dAta分析使用柱状存储的魔力。

在Uber使用Presto

我们选择Presto作为我们的系统SQL引擎,因为它可扩展性、高性能、平滑集成Hadoop.这些特性使它非常适合我们的许多团队。

转眼间架构

Uber的Presto生态系统由处理存储在Hadoop中的数据的各种节点组成。每个Presto集群都有一个“协调器”节点,用于编译SQL和调度任务,以及许多联合执行任务的“工作者”节点。如图1所示,客户端将SQL查询发送给我们的Presto协调器,它的分析器将SQL编译成一个抽象语法树(AST).

从那里,计划器将AST编译为查询计划,将其优化为碎片器,然后将计划分割为任务。接下来,调度器将每个任务(从Hadoop分布式文件系统(HDFS)读取文件或进行聚合)分配给特定的工作人员,节点管理器跟踪其进度。最后,这些任务的结果被流式传输到客户端。

图1:Uber的Presto架构包含了一个分析和调度任务的协调节点和几个扫描和聚合数据供客户端使用的工作节点。

Hadoop基础设施和分析

Uber的所有分析数据集都捕获在我们的Hadoop仓库中,包括由卡夫卡,面向服务的体系结构表构建MySQL和Postgres,行程数据存储在无模式.我们运行Flink黑比诺,MemSQL用于数据流和实时分析。

Hadoop分布式文件系统(HDFS)是我们的数据湖。在这个生态系统中,事件日志和行程数据使用Uber内部数据摄取工具摄取,面向服务的表通过复制到HDFSSqoop.与超级连帽衫, Uber的增量更新和插入库,数据首先作为嵌套的原始文件转储到我们的HDFS中,然后通过提取,转换,加载(ETL)作业将其中一些原始表转换为建模表。而批处理和ETL作业继续运行蜂巢而且火花,在Presto上运行接近实时的交互式查询

这个健壮的Hadoop基础设施集成在Uber的数据中心中,结合了现有的全活动、可观察性、集群管理和安全特性。

图2:由我们的技术堆栈支持,Uber的Hadoop基础设施从各种来源捕获和存储数据。

柱状存储方便访问

Uber数据被转储到HDFS,并注册为原始表或建模表,这两个表都可以通过Presto查询。

原始表不需要预处理,并且是高度嵌套的;超过五层嵌套的情况并不少见。由于Hoodie的处理能力,原始表数据摄取延迟约为30分钟。

另一方面,使用ETL预处理作业对建模表(访问频率更高)进行更仔细的选择和平面化。建模表的数据摄取延迟要高得多;大多数建模表的摄入延迟为8到24小时。

由于我们的数据规模和分析的低延迟要求,我们将数据存储为列而不是行,这使得Presto能够更有效地回答查询。由于不必扫描和丢弃行中不需要的数据,柱状存储节省了磁盘空间,并提高了大型数据集的查询性能。

进入拼花

我们选择Parquet作为Uber的Hadoop存储解决方案是因为它的压缩和编码功能,以及它对嵌套数据集的基本支持。这些特性允许我们的查询引擎(包括Presto)达到最高的性能和查询速度。

图3:Parquet是Uber Engineering为Hadoop生态系统提供的存储解决方案,它将数据水平划分为行,然后垂直划分为列,以便于压缩。

在Parquet中,数据首先水平划分为行组,然后在每个组中,数据垂直划分为列。特定列的数据通过压缩和编码存储在一起,以节省空间并提高性能。每个Parquet文件都有一个用于存储的页脚编解码器,编码信息,以及列级统计信息,例如列值的最小和最大数目。

在理论上,Parquet与我们的Presto体系结构是完美的匹配,但是这种魔力会转移到我们系统的柱状需求吗?

一个新的拼花读卡器Presto

Parquet在Presto中使用原始的开源来支持镶花的读者.虽然这个阅读器可以很好地与开源Presto一起使用,但它既没有完全集成柱状存储,也没有使用Parquet文件统计数据进行性能优化,因此对我们的用例无效。

为了解决这个性能问题,我们开发了一个新的拼花读卡器Presto在我们的数据分析系统中充分利用Parquet的潜力。下面是一个示例查询,根据预期的乘客需求确定在给定日期特定城市的目标司机:

选择base.driver_uuid
从rawdata.schemaless_mezzanine_trips_rows
WHERE datestr = ' 2017-03-02 ' AND base。City_id in (12)

在这个场景中,嵌套表rawdata.schemaless_mezzanine_trips_rows在Parquet中存储了超过100tb的原始旅行数据。通过上面的示例,我们将演示如何使用原始的开源阅读器和我们自己发明的开源阅读器来处理查询。

原始开源拼花阅读器

图4:最初的开源Parquet阅读器没有完全结合柱状存储,这使得分析大型Uber数据集效率低下。

原阅读器分三步进行分析:(1)使用开源Parquet库逐行读取所有Parquet数据;(2)将基于行的Parquet记录转换为内存中所有嵌套列的柱状Presto块;并且(3)求出谓词(base.city_id = 12),在我们的Presto引擎中执行查询。

Uber的新Parquet阅读器

为了适应Uber数据的大小和规模,我们创建了一个新的开源Parquet阅读器更有效地使用内存和CPU。这个新的读取器实现了四项优化,旨在提高性能和加快查询速度。

嵌套列修剪

图5:Uber的新开源阅读器可以通过嵌套列修剪跳过不必要的数据。

新阅读器优化查询的一种方法是跳过不必要的数据,称为嵌套列修剪。顾名思义,这种优化在用于嵌套数据时最为有效。

新的读卡器执行嵌套列修剪分为三个步骤:(1)只读取Parquet中需要的列;(2)将基于行的Parquet记录转换为柱状块;(3)在Presto引擎的柱状块上计算谓词。

柱状读取

图6:我们的新阅读器通过直接读取列而不是逐行读取来增强查询。

新的阅读器还可以直接读取Parquet中的列,而不是逐行读取,然后执行行到列的转换,这加快了查询速度。它分两步执行柱状读取:(1)只读取Parquet中需要的列并动态构建柱状块,节省CPU和内存将基于行的Parquet记录转换为柱状块;(2)在Presto引擎中使用柱状块计算谓词。

谓词下推

图7:谓词下推允许我们跳过读取Parquet行组来保存磁盘IOs。在这个例子中,查询正在寻找city_id = 12,一个行组city_id max是10,新的Parquet读取器将跳过这个行组。

使用我们的新阅读器,我们可以在扫描Parquet文件时计算SQL谓词。通过使用Parquet统计数据,我们还可以跳过读取文件的部分内容,从而节省内存并简化处理。谓词下推主要用于“大海捞针”查询。

新的读取器通过将三个操作合并到一个步骤中来执行谓词下推:同时读取Parquet中所需的列,动态计算柱状谓词,并构建柱状块。在此场景中,如果谓词与正在查询的谓词不匹配,则读取器将跳过读取一组行。

字典叠加

图8:像谓词下推一样,字典下推在一个步骤中执行,在为Presto引擎构建柱状块的同时,同时读取和计算数据列。在本例中,查询查找city_id = 12;因为一个行组的city_id字典包含id 3、5、9、14、21,所以新的读取器将跳过这个组。

即使Parquet统计信息匹配谓词,我们也可以为每一列读取字典页面,以确定字典是否可能匹配谓词。如果不是,我们可以跳过读取行组。与谓词下拉一样,字典下拉使查询更快,对于大海捞针查询最有效。

我们的新阅读器也只需要一个步骤就可以执行字典下推:在Parquet中读取所需的列,动态计算柱状谓词并构建柱状块。与谓词下拉类似,如果字典值与谓词不匹配,则字典下拉允许阅读器跳过行读组。

懒惰的读取

图9:只有在匹配谓词时才执行惰性读取,从而节省CPU和内存。

我们的阅读器也可以被设定为尽可能慵懒地阅读投影专栏。这意味着我们只在投影列与谓词匹配时才读取它们,从而加快了查询速度。

惰性读取在一个步骤中执行:在Parquet中读取所需的列,动态计算柱状谓词,仅在谓词匹配时构建柱状块。

这四项优化都是Uber的Parquet阅读器所独有的,确保了我们的数据存储和分析的有效使用。自从将新的Parquet读取器投入生产以来,数据处理速度比使用原始开源读取器快2-10倍。

图10:我们的新阅读器为Uber的基准SQL查询演示了2-10倍的加速。

正在进行的工作

随着时间的推移,Presto已经成为分析我们的用于大规模大数据的交互式SQL查询。自2016年部署以来,我们的Presto集群已超过300个节点,是有能力的访问超过5pb的数据,并在60秒内完成90%以上的查询。当你的技术堆栈中有这样的魔法时,谁还需要从帽子里变出兔子呢?

即使有了这些指标,我们的团队仍然在积极提高Presto的可靠性、可伸缩性和性能,以使我们的数据分析尽可能高效。正在进行的工作包括:一个PrestoElasticsearch连接器,多租户资源管理,Presto协调器的高可用性,地理空间功能支持和性能改进,以及缓存HDFS数据。

如果你有兴趣加入我们的分析魔术师团队,请申请Uber的职位数据基础设施团队。

Zhenxiao罗他是Uber Hadoop基础设施和分析团队的软件工程师。目前,他负责优步Presto的开发和运营。

图片标题:Conor Myhrvold的《大象泼泥降温》,奥卡万戈三角洲,博茨瓦纳。

评论