2

极牛技术实践分享活动
极牛技术实践分享系列活动是极牛联合顶级VC、技术专家,为企业、技术人提供的一种系统的线上技术分享活动。
每期不同的技术主题,和行业专家深度探讨,专注解决技术实践难点,推动技术创新,每周三20点正式开课。欢迎各个机构、企业、行业专家、技术人报名参加。

嘉宾介绍
付力力,前百度大数据部资深工程师,神策数据联合创始人&架构师,熟悉海量数据处理、数据仓库、大规模OLAP分析等领域。

基本概念

数据查询引擎是大数据处理架构的核心组件之一,通常是面向数据应用层的直接接口。下面是一个比较典型的数据金字塔的架构图:

clipboard.png

数据查询引擎并没有严格的定义,不过一般来说一个典型的数据查询引擎都会有以下几个特点:

1) 可以访问结构化数据
2) 提供 SQL 或者类 SQL 的查询接口
3) 返回结构化的查询结果

不过虽然都叫查询引擎,不同查询引擎的特性却是千差万别的,各自适用的场景也不太一样。

clipboard.png

这个图是一个比较典型的用户行为分析场景下使用查询引擎的架构图

一般我们会从以下几个指标来评价一个查询引擎的特征和它适用的场景。

1) 可扩展性:是单机还是分布式?
2) 支持的数据量级:支持几个 GB,还是数百 TB?
3) 支持的数据格式:要求特定格式,还是可以适应各种格式?
4) 响应时间:毫秒?秒级?分钟?
5) 查询能力:完全 SQL 支持?还是部分支持?或者是完全不支持?

但是基本上不存在一个查询引擎能在以上所有的指标上都做到最好,一般还是需要根据具体的需求来选择。

通常来说,使用查询引擎的应用场景主要有以下两个大的类别:

第一类是数据处理类应用

比如对数据进行格式转换、按条件抽取数据、做各种数据预处理等。对于这类应用来说,输出的数据量可能和输入是同等数量级,甚至更大;并且运行的时间也比较长,例如在小时级甚至天级。

第二类是统计分析类,比如计算网站/App 的访问量、留存率等等。

这类应用输出的结果往往是需要直接展示给终端用户看的,所以通常都比较小,一般在 MB 或者 KB 级别,多数时候可能就是几个数字。而且此类应用通常都要求交互式响应,比如在几秒或者最多几分钟就返回查询结果。

所以非常明显,以上两大类需求点对于查询引擎的要求其实是很不一样的。在实际使用上,我们需要根据更加具体的应用场景来选择合适的数据查询引擎。

主流查询引擎的特点和比较

01 | Hive

首先来看看 Hive,Hive 出现的时间比较早,应该是目前使用范围最广的数据查询引擎之一了。Hive 最大的特点是灵活性:它支持标准的 SQL、支持多种数据格式(文本、ORCFile、Parquet)、支持多种存储引擎(HDFS/HBase)等等,甚至在执行层面,还支持多种执行引擎(MapReduce/Tez/Spark)。

clipboard.png

缺点也很明显,就是执行性能比较一般。原因之一是它很难针对各种情况做针对性的优化。

但是 Hive 可以说是一个比较纯粹的查询引擎,它本身不包含执行层和存储层,所以具有很高的适应性,可以在各种环境下运行。所以 Hive 通常适合数据处理类的应用,比如最常见的是做一些ETL。同样是做ETL,相比写MapReduce或者Spark会简单很多。而且因为执行依然是MapReduce等引擎,所以稳定性也比较好,适合长时间运行。但是对于交互式的分析就不太合适,比如一个简单的COUNT(*)可能要执行数分钟。

02 | Impala

接下来我们看看 Impala,这也是一个出现频率比较高的查询引擎。

clipboard.png

这个是Impala的架构图,可以看到Impala是对Hive有一些模块上的依赖,它复用了Hive的元数据。

简单的说,就是可以直接查询Hive里的表。它在查询功能上的支持和 Hive 比较类似,包括对各种SQL语法的支持。不过 Impala 最大的特点是有自己的 MPP 架构的执行层,而不是依赖于 MapReduce或者Spark之类的,所以查询性能比Hive要高很多。当然,Impala 对资源,尤其是内存的需求也比较高。而且它的容错性不如 Hive,使用不当的话很容易挂掉。准确的说是容错性不如 MapReduce/Spark,比如容易超内存。所以对于长时间的查询是不太合适的,比如不适合用来做ETL。很可能一个查询跑了一个小时,然后最后关头挂掉了,又得从头开始执行。但是它非常适合统计分析类的应用,可以做到秒级响应。尤其是配合Parquet的列式存储,可以达到很高的查询性能。

总结一下,Impala和Hive的区别主要是在于执行层,因此也造成了它们两个应用场景上的差异。

还有一个 Presto,Facebook开源的。因为它在整体架构、思路都和 Impala 比较像,这里就不再细说。

03 | Spark SQL

接下来,我们再看一下最近比较火的 Spark SQL

clipboard.png

Spark SQL是Spark生态的一部分,它最大的特点是基于 Spark的引擎来执行,也因此可以和 Spark 的其它计算方式无缝融合。它也复用了Hive的元数据、UDF之类的资源。

Spark SQL最大的特点是可以在原有的Spark代码里使用SQL来进行中间数据的处理,很多时候可以简化复杂的数据处理流。

Spark SQL 的适用范围相对比较广。数据处理类肯定是它的强项,而它在查询响应时间上也比 Hive 要强不少,某些场景下也接近Impala,因此也可以用于某些在线分析的场合。

它现在的主要缺点是成熟度一般,不过最近发展很快。Spark SQL对内存的消耗也相对会比较大,相比Hive。Impala/Spark SQL都兼容和复用了Hive的一部分组件。这个原因之一也是因为Hive推出时间早、使用范围广,所以兼容Hive可以很大程度上降低使用门槛。

04 | Druid

然后再看看 Druid,这也是最近很火的一个开源组件。

准确的说 Druid 并不是一个查询引擎,它是一个完整的数据库,包含了查询引擎。不过 Druid 并不支持 SQL,而是使用了 JSON 来进行查询描述,暂时也不支持复杂的 JOIN 类的查询。但是,Druid 通过预聚合和索引提供了高 QPS、低延时的查询能力,非常适合在线报表类的应用。

clipboard.png

这是Druid的数据流图,可以看到Druid并不依赖Hive或者HDFS,而是有自己的查询引擎和存储引擎,也不像Hive/Impala之类的支持多种数据格式,而是必须导入转换为它自己的存储格式。

和 Druid 类似的产品还有Pinot,但是成熟度和流行成都目前都不如 Druid。这里也不再细讲。

上面就是几个我比较了解的主流查询引擎的简单介绍。可以看到,不同查询引擎的架构、指标特性都有很大的区别。

典型场景应用

接下来我们再来看看在几种典型的应用场景下,应该选用什么样的数据查询引擎。

场景一:假设有一个小规模的数据应用,总体数据量在几十GB或者更低。

在这种场景下,我们不太建议用任何复杂的开源方案,而是直接使用成熟的分析型数据库,例如 Vertica、Greeplum、Redshift 等等等等。这些数据库不管在功能的完善程度、系统的稳定性,还是在查询优化上都已经做的非常好了,不需要从头开始踩坑。当然它们的主要缺点是需要先进行 ETL 入库,也就是需要导入数据,这个可能会消耗一些资源和时间。但是如果数据量不大,这一点也完全不是问题,而且导入之后会更方便管理。比如可以任意的增删改查。当然,使用这类数据库在规模大了之后,扩展性和成本上会出现比较多的问题,因此一般只适合小规模的应用。

场景二:假设是一个典型的大规模数据仓库,数据量可能在几十TB或者更大,数据源也是非常多样化,可能有各种不同格式的文本数据,也有各种二进制数据。

因为数据源的多样性,对于数据的需求也会是非常多样化的,比如即有数据预处理,也有统计分析或者更进一步的数据挖掘需求。而且不同数据之间还需要非常方便的互相引用。

一般来说,在这样一个大规模数据量的场景下,首先需要尽量避免的就是ETL的成本。比如我们不能因为要进行一次偶然的数据查询,就需要把数百 TB 的数据进行一次高成本的 ETL,这个资源消耗是非常大的,而是希望想查的时候随时可以直接查。为了解决这个问题,首先我们可以使用 HDFS 来进行统一的数据存储,先解决存储层的问题,这样无论是什么数据都可以直接访问到。然后再配合 Hive 或 SparkSQL 解决数据处理类应用的问题,对于统计分析类应用,则可以使用 Impala 或 Presto 解决。主要是因为这里提到的几个查询引擎都可以很好的支持 HDFS 上的多种数据格式,可以很好的避免不必要的数据迁移和 ETL 开销。而且,这些数据也可以很容易的和MapReduce、Spark之类的计算进行进一步的融合,具有很高的灵活性,而不只是局限在某个具体的数据存储里。

场景三:我们来看看比较典型的用户行为分析类型的应用。

这类应用的特点是:要分析的数据里包含时间维度、并且有可能有额外的数百个不同的维度,而且对于分析灵活性的要求很高,同时查询的模式也并不固定。

clipboard.png

比如这是一个典型的用户行为分析的数据表,每一行代表一个用户的行为。

这类应用要求单次分析的响应时间不能太长,不然没法做到交互式的分析体验。所以,使用 Impala/Presto 是比较合适的,因为它们即有比较高的查询性能,又支持包括 JOIN 在内的各种复杂查询,同时配合列存还能最大程度的减少 IO 开销。

不过,对于大时间跨度的复杂查询,可能还是会存在查询时间较长的问题。这种时候一般可以通过预聚合、抽样等手段来进行进一步的优化。而且分析类的应用对于响应时间并没有那么敏感,一个复杂的查询跑几分钟还是可以接受的。

场景四:运维监控类/广告统计类的需求。

这类应用和用户行为分析类有点类似,但是最大的区别是,它们在维度和查询模式上都通常比较固定,比如都是按小时/天/月来聚合查看各种监控指标的曲线。

但是对查询频率和响应时间的要求则比较高,一般都需要秒级。这种场景下,使用 Druid 这种可以预聚合的查询引擎是比较合适的。经过预聚合之后,100G的数据可能只有1G或者更小,在进行比较粗粒度(例如按天)的查询时,可以达到非常高的性能。

常用优化方案

首先是数据预聚合,前面也多次提到过。这是一种非常常见的优化手段,可以有效的减少查询扫描的数据量。

虽然 Druid 是内置直接支持预聚合,但是不代表其它查询引擎不能使用预聚合。不过预聚合是需要在消耗额外的计算资源的,同时也可能还会带来更大的维护成本。任何查询引擎都可以使用预聚合的方案来优化性能,不过如何合理的创建、选择和使用聚合表,还是比较困难的。如果用不好很可能起到反作用。

另外一种常见的优化手段是进行数据抽样

也就是以牺牲一定的数据准确性的方式来减少对资源的消耗,同时优化查询的响应时间。数据抽样在数据量非常大的时候是很划算的一种做法,尤其是在目前存储资源很便宜、计算比较昂贵的情况下。但是具体如何进行数据抽样通常还是由业务决定,不能一概而论。比如一般做用户行为分析就按用户ID来进行抽样是比较合适的。不过大部分查询引擎并不支持原生的抽样功能。如果想要实现准确、快速的数据抽样,通常需要存储端的配合,可能需要进行深度的定制修改。

最后是数据索引的优化,这个是传统数据库的常见优化手段,不过在大数据查询引擎里也可以使用的。

使用索引可以实现针对某些维度的快速筛选,当然同时也会带来的额外的计算和存储成本,而且不是任何查询模式都能命中索引,通常只是针对特定业务需求的优化。很多优化手段可能需要对查询引擎本身做改动才能实现的,这个时候使用开源组件就会体现出比较大的优势。

Q&A:

Q1:了解数据查询引擎的工作原理对我们的业务可以有什么帮助?
A1:主要是在面对不同需求的时候应该如何选择合适的查询引擎来作为技术选型,比如做网站流量分析、广告统计、运维分析等等。

Q2:你们的产品Sensors Data用了什么数据查询引擎,和Google Analytics、Mixpanel的方案有什么差异吗,为什么?
A2:Sensors Data主要是用了Impala,不过单机版也支持其它的查询引擎。GA的实时计算报表部分应该用的他们内部的引擎(和对外的big query是一套架构)。Sensors Analytics和Mixpanel整体架构和思路上应该还是比较像的,都是以实时分析为主,不过Mixpanel是纯SaaS,具体实现我们也不清楚。

本次分享来自于极牛技术实践分享系列活动。 更多技术干货关注微信公众号“极牛”。


极牛
110 声望25 粉丝