一览美图数据开发与SQL解析

感谢阅读「美图数据技术团队」的第 16 篇原创文章,关注我们持续获取美图最新数据技术动态。

2008 年成立至今美图打造了数款 App 产品,而随之带来的是扑面而来的用户数据与其相关的业务需求。多种业务需要不同的统计方式,数据量的暴涨意味着维护成本也在同步提高,愈来愈多的重复性工作......这些都是美图进行数据「改革」的主要因素。

图 1

如图 1 所示是最初始的需求提出到完成的具体流程,其中服务端设计接口并产生日志,统计人员需要和服务端确认接口,开发统计上线,期间需要反复与服务端人员沟通,时间成本较大。各种业务场景都是由各自产品提需求给统计小组,复杂的业务分析使得沟通和执行成本较大,长期的效果跟踪下需求不断变更,产品端的数据分析人员对各自产品更加敏感,能更灵活的调查。

根据以上问题我们在各个问题爆发的阶段采取不同的策略对应:

  • 人力对接方式 统计研发人员对接需求,写MR或HQL,定时脚本部署取数据
  • 平台化 需求爆发、变更,代码重复,脚本难以维护,开发平台来解决、维护数据需求
  • 业务配置版 业务爆发,统计业务多样性,由业务研发人员自助配置统计需求
  • 数据分析表 数据分析需求爆发,数据分析师自助取数分析
  • 任务依赖升级 任务复制的依赖关系,接入调度系统

通过一系列的改版迭代,在数据开发过程中减少沟通成本、加快开发周期、减少重复开发工作、不惧需求变更、节约维护成本、提高数据质量.....

/ 结构设计与实现原理 /

图 2

如图 2 所示是系统的架构设计,主要分为两个模块:Manager 与 Scheduler。其中 Manager 包括系统界面管理模块和任务管理模块,任务管理模块包括任务配置、调度配置、插件配置、用户信息配置等 Meta 信息。Scheduler 负责任务执行生命周期与任务实例插件初始化、数据抽取、转换、写入、日志记录等。

接下来看看任务执行的主要流程:

图 3

首先用户提交执行任务,Manager 验证参数并向 Scheduler 发起执行任务,返回提示信息给用户。接着 Scheduler 初始化任务实例 Workflow,加载配置信息,Workflow 初始化任务配置的插件(SourcePlugin、TargetPlugin 以及 Udf)。SourcePlugin 连接数据源,执行抽取数据,Udf 对抽取的数据进一步加工,进行聚合等。TargetPlugin 连接数目标数据源,把抽取的数据写入指定目标库(如执行 Mysql Insert 写入数据)。最后完成 Workflow 执行,记录完成信息。

图 4

值得注意的是,每个 Workflow 实例都会执行 SourcePlugin.extract、Udf、TargetPlugin.loading。

插件接口主要有两个方法:extract、loading,extract 定义为抽取数据,loading 定义为写入数据。每个具体的插件实现以上两个接口即可,之后有其他数据源可以方便扩展,通过以下图表了解整体插件:

图 5

/ 系统核心 feature /

上文中有提到在美图数据平台化之后,由于业务需求与数据分析需求的爆发我们搭建了业务配置版数据分析版两种平台,其中在业务配置版本业务方只要按一定规范进行日志记录,即可在平台进行简单的任务配置并调用统计接口获取数据进行展示。业务方可以进行如下配置:

数据来源

对接数据之后,数据将会分类并映射为 hive 表,比如美拍有服务端接口日志 meipai 表;

分组维度

根据数据接入时候定义字段,如美拍日志中的 client_id,分组维度相当于 group by 所需字段。

统计维度

需要统计的方式和目标,支持计数、去重、求和、top,选择计算方式之后,需要再选择计算目标,比如对 device_id 计数、对金额求和,结合统计方式形成如 count(device_id),count(distinct device_id)的sql 形式。

过滤条件

对日志进行条件过滤设置,支持 or 和 and,不同组之间的条件关系为 or,组内的条件为 and,类似于 sql 中的 where (a and b ) or (c and d);支持各种条件过滤逻辑。

聚合维度

支持聚合功能,可自由选择聚合的维度和聚合后分组维度的代替值。

接口访问

需任务配置完成生成 api ,经过授权即可访问数据。

数据分析版本面向有一定 sql 敏感度的数据分析人员或者服务端人员,该版本提供一个分析平台并支持下载数据,它有以下功能:

快速校验错误语法

基础语法检验,即时反馈 sql 语法中的错误;

危险语法限制

drop、insert 基础表数据等;

⾼资源损耗验证

限制查询的时间范围,通过 partition 的日期字段判断每个子查询的时间范围的有效性。

先来看看 Hive 的简要架构图,在 Hive 的架构中,Compiler 完成 HQL 查询语句从语法解析、语义解析、编译、优化以及生成查询计划等工作。

图 6

其中 HQL 转化成 mapredurce 的过程,分为以下 6 个阶段:

图 7

*AST:抽象语法树;QB:查询基本单元QueryBlock;OP Tree:执行操作树;Task Tree:任务树。

1.HQL 词法、语法解析,将 HQL 转化为抽象语法树 AST

语法解析阶段,Hive 利用 Antlr 将用户提交的 HQL 语句解析成一棵抽象语法树。

*ANTLR(Another Tool for Language Recognition),一个通过语法描述来自动构造自定义语言的识别器(recognizer),编译器(parser)和解释器(translator)的框架。

图 8

这里以一个简单的 sql 来说明 AST 的各个节点,图中生成一个 TOK_INSERT 节点,这个节点是在语法改写中特意增加了的一个节点。原因是 Hive 中所有查询的数据均会保存在 HDFS 临时的文件中,无论是中间的子查询还是查询最终的结果,Insert 语句最终会将数据写入表所在的 HDFS 目录下。

2. 遍历 AST,抽象出查询的基本组成单元 QueryBlock

AST 仍然非常复杂,不足以结构化也不方便直接翻译为 MapReduce 程序,AST Tree 转化为 QueryBlock 就是将 SQL 进一部抽象和结构化。

QueryBlock 是 SQL 最基本的组成单元,它包括三个部分:输入源、计算过程、输出。简单讲一个 QueryBlock 就是一个子查询。

*QB#aliasToSubq(表示QB类的aliasToSubq属性)保存子查询的QB对象,aliasToSubq key值是子查询的别名;

QB#qbp即QBParseInfo保存一个基本SQL单元中的各个操作部分的AST Tree结构; QBParseInfo#nameToDest这个HashMap保存查询单元的输出,value是对应的ASTNode节点,即TOK_DESTINATION节点。类QBParseInfo其余HashMap属性分别保存输出和各个操作的ASTNode节点的对应关系;

QBParseInfo#JoinExpr保存TOK_JOIN节点; QB#QBJoinTree是对Join语法树的结构化; QB#qbm保存每个输入表的元信息,比如表在HDFS上的路径,保存表数据的文件格式等; QBExpr这个对象是为了表示Union操作。

3. 遍历 QueryBlock,翻译为执行操作树 OperatorTree

该步骤是把查询单元 QB 转换操作树。操作树由多个操作符组成,每个操作符在 Map 阶段或者 Reduce 阶段完成单一特定的操作。以下是基本的操作符:

图 9

QueryBlock 生成 Operator Tree 就是遍历上一个过程中生成的 QB 和 QBParseInfo 对象的保存语法的属性,各个属性对应生成操作符,包含如下几个步骤:

QB#aliasToSubq => 有子查询,递归调用 QB#aliasToTabs => TableScanOperator QBParseInfo#joinExpr => QBJoinTree => ReduceSinkOperator + JoinOperator QBParseInfo#destToWhereExpr => FilterOperator QBParseInfo#destToSelExpr => SelectOperator QBParseInfo#destToGroupby => ReduceSinkOperator + GroupByOperator 最终都解析完后,会生成一个 FileSinkOperator,(将数据写入 HDFS)

由于 Join/GroupBy/OrderBy 均需要在 Reduce 阶段完成,所以在生成相应操作的 Operator 之前都会先生成一个 ReduceSinkOperator,将字段组合并序列化为 Reduce Key/value, Partition Key。

4. 逻辑层优化器进行 OperatorTree 优化

优化器类型如图 10 所示:

图 10

5. 遍历 OperatorTree,翻译为 MapReduce 任务

以下是操作符生成对应 mr 任务的具体规则:

图 11

该过程分为 5 个阶段:对输出生成 FetchTask;从 OperatorTree 的其中一个根节点向下优先遍历;ReduceSinkOperator 标示 Map/Reduce 的界限,多个 Job 间的界限;遍历其他根节点,遇到 JoinOperator 合并 MapReduceTask;剪断 Map 与 Reduce 间的 Operator 的关系。

6. 物理层优化器进行 MapReduce 任务的变换,生成最终的执行计划

以下是各种物理层优化器的作用:

图 12

过程中值得注意的是:

对用户提交的 sql 进行校验与限制,主要复用了第一阶段生成的 AST 和第二阶段生成的 QB; 递归 QB 从 AST 的节点获取操作、表、查询条件等信息; 判断操作和表是否有危险行为与权限,主要为 drop、insert; 查询条件解析出分区字段,验证分区字段必填和时间范围。

原文发布于微信公众号 - 美图数据技术团队(gh_feb1d206d92b)

原文发表时间:2018-09-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据和云

数据库时间出现'0000/00/00',难道我穿越了?

前几天有个朋友遇到一个问题,在做日期类型数据的运算的时候出现了‘0000-00-00’的结果,不得其解。你是否遇到过同样的问题呢?这样一个并不存在的时间点,难道...

3086
来自专栏about云

Spark利用Project Tungsten将硬件性能提升到极限

我们将为你介绍性能提升的下一阶段——Tungsten。在2014年,我们目睹了Spark缔造大规模排序的新世界纪录,同时也看到了Spark整个引擎的大幅度提升—...

3887
来自专栏PingCAP的专栏

TiDB 源码阅读系列文章(十五)Sort Merge Join

在开始阅读源码之前, 我们来看看什么是 Sort Merge Join (SMJ),定义可以看 wikipedia。简单说来就是将 Join 的两个表,首先根据...

1340
来自专栏架构师之路

如何快速实现高并发短文检索

一、需求缘起 某并发量很大,数据量适中的业务线需要实现一个“标题检索”的功能: (1)并发量较大,每秒20w次 (2)数据量适中,大概200w数据 (3)是否需...

3388
来自专栏祝威廉

ElasticSearch Aggregations 分析

我记得有一次到一家公司做内部分享,然后有研发问我,即席分析这块,他们用ES遇到一些问题。我当时直接就否了,我说ES还是个全文检索引擎,如果要做分析,还是应该用I...

903
来自专栏木头编程 - moTzxx

PHP 开发学习[6] —— PHP导出Excel表实例参考

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

832
来自专栏大数据和云计算技术

一套数据,多种引擎(续)---两种数据格式(Parquet/ORCfile)浅析

最近主要在研究大数典型应用adhoc query,要实现秒级的adhoc query,通常有3种思路: 1、用搜索技术,将查询都建立索引,然后用搜索技术来实现。...

37310
来自专栏Golang语言社区

C++ 实现银行排队服务模拟

教程简介:使用 C++对银行排队服务进行模拟,以事件驱动为核心思想,手动实现模板链式队列、随机数产生器等内容,进而学习概率编程等知识。作为可选进阶,这个模型同时...

37812
来自专栏用户画像

13年5月 软考笔记整理

虚拟存储器为了给用户提供更大的随机存储空间而采用的一种存储技术。它将内存(主存)与外存(辅存)结合使用,好像有一个容量巨大的内存储器,工作速度接近于主存,每位成...

923
来自专栏牛客网

后台开发:校招中遇到的问题总结

楼主的秋招也算是今天开始结束了,期间也迷茫过,最终拿到了百度sp、腾讯sp、360sp、京东、招行信用卡中心、华为、中兴、陌陌sp 等的offer(具体的面经前...

5719

扫码关注云+社区