dbaplus社群 + 关注
手机版

突破DBMS局限性,阿里借力Spark提升查询性能

  1. 云栖社区>
  2. dbaplus社群>
  3. 博客>
  4. 正文

突破DBMS局限性,阿里借力Spark提升查询性能

技术小能手 2018-11-05 17:14:43 浏览778 评论0

摘要: 我们知道SQL Server是一款技术上和商业上都很成功的产品,这一次微软选择拥抱Spark大数据生态,着实令人有些惊讶。国内的几款产品也丝毫不落后,阿里云的DRDS、腾讯云TDSQL也都各自推出了与Spark相融合的产品。

我们知道SQL Server是一款技术上和商业上都很成功的产品,这一次微软选择拥抱Spark大数据生态,着实令人有些惊讶。国内的几款产品也丝毫不落后,阿里云的DRDS、腾讯云TDSQL也都各自推出了与Spark相融合的产品。

今天我们就来谈一谈,如何在数据库这个老生常谈的话题下,借力Spark给数据库带来新的价值。

一、传统数据库的不足

不用多说,MySQL是互联网企业中使用最广泛的数据库。但是MySQL专注于OLTP能力,对复杂的分析型查询并不在行。为什么这么说呢?

这是由MySQL的整个系统设计决定的,MySQL从最初就被设计为每个请求由单线程来处理。之所以这么设计,是因为OLTP查询大多很简单,SELECT多以点查居多,让一个线程来处理已经足够了。

在后来的改进中,MySQL增加了线程池、高低优先级等等,但是仍未改变其本质:一个线程对应一个查询请求。

5633fb68344393bfed0faf598382f52ec2226775

对于这样的架构,即使增加机器配置,对提升OLAP查询性能也没什么显著帮助,因为无法利用多核并行的能力。

MySQL之上有很多支持水平拆分的分布式方案,能让数据均匀分摊到多个节点上,从而获得Scale Out的能力。以阿里云DRDS(分布式关系型数据库)为例,DRDS支持分布式事务、平滑扩容、读写分离、权限管理等特性,架构如下图所示:

cfaa0ab92c577835ac0a6b61f2975f37ef1c22fa

通过合理选择Sharding方式,我们可以在这种架构上比较好地处理一些聚合Join等查询。但是,如果数据量较大,例如遇到难以索引的ad-hoc查询,这一架构同样力不从心。

二、解决OLAP难题

一般解决OLAP有两种思路。最常见的思路是,在业务库之外再拷贝一份数据,搭建数据仓库。大多数数仓都采用分布式MPP架构,MPP全称是Massively Parallel Processing,即大规模并行处理,顾名思义是用多节点并行计算的方式来加速复杂查询计算;另一方面,数仓大多使用share-nothing架构,数据被分片存储到各个节点上:

6ac921aec5e93383b616c03bfbc13bbf67c6b32f

上面的思路有时也被称为ROLAP,与此相对的,另一种方案是跳出查询本身:MOLAP通过对数据进行预建模来加速查询。例如,我们通常选择时间维度、加上若干个业务维度,对它们的各种组合方式预先做好聚合。

0a2a24cfa1b5b73f00f8362cb91c2994490b965c

下图就是一个例子:

40a0ea50127f6d0ee85945995d25d75013e2d30f

从(year, item, city)三个维度枚举出8种组合方式,我们对这8种方式的聚合都进行预先计算,这有时也被形象地称为Data Cube。

如果用户查询与预建模匹配,只需要在之前聚合结果的基础上再做计算就行了,显然,查询代价大大减少。MOLAP的典型代表是Apache Kylin。

但很显然,MOLAP所能计算的查询严格受建模方式限制,这让它的门槛大大提高。所以综合来看,使用的不如ROLAP广泛。

三、Spark与Spark SQL

Spark是当下最流行的大数据框架,支持编程接口和声明式(SQL)接口,支持批处理任务和流计算任务。它使用Scala编写,支持Java、Scala、Python等语言的编程接口。

虽然我们常常把Spark归入Hadoop生态系统中,但事实上Spark并不依赖Hadoop,只是因为Spark本身不包含存储,通常和HDFS一起部署搭配使用。

Spark的设计比MapReduce更先进。为什么这么说?

我们回顾一下MapReduce模型:MapReduce处理复杂任务需要分成多个MR Stage,每个Stage都要写入中间结果到HDFS,之后再被下个Stage读出。之所以要持久化中间结果,目的是要达到Worker级的失败容忍,但是这个代价过于大了点。

141551be42ef2e8014c8b4aae1a3fa12d05f6e7a

Spark RDD模型中,则采用另一套失败容忍方案。

Spark假设所有计算都是确定性的,因而也就可以通过重算恢复丢失的分区,避免写HDFS、把数据尽量放在内存,性能得以大大提告。

RDD全称是“弹性分布式数据集”,“分布式”意为每个RDD都包含多个分区、分布在多个节点上;“弹性”意为每个分区都可以容易的被恢复——只要它的依赖方还在,就可以重算来恢复。

a18b75be99f8c759173509c2aa40623f97abf4c1

Spark的查询计划包中,像filter、map这些算子是可以在分区内部以pipeline的方式执行的;但另一些算子,例如Join,通常需要在Join之前对左右两边的数据都按Join Key做Shuffle,这就导致想要执行Join之前必须等待左右所有数据都完成才能继续。这个点被称为Pipeline-breaker。执行计划中,不可避免地会出现几个Pipeline-breaker,所以就也产生了多个Stage,这和MR有些相似。

4d6f44cc2fe08f5e0cd2c544d95355626c6e0bee

查询执行的时候,我们沿着Stage的依赖关系从左往右计算即可,例如对于上图,先执行Stage 1、Stage 2(二者可以并行),再执行Stage 3。Stage内部则以pipeline方式执行。

Spark SQL则是在Spark RDD API上的二次封装,下图是一段Native API的例子:

7cf1d14f965df00c6f08fb4e0748e2f4b663063a

此外也可以直接输入SQL,二者无非是是否经过Parser的区别。

bedaf774aacb7b7a137e88b84c07b2dc8f3832a8

四、为什么用Spark?

之前说到,MySQL那样的架构不足以满足我们对复杂查询的需求。本着透过现象看本质的精神,让我们重新审视一下各种DBMS以及大数据的执行方式,无非是以下几种:

 ●  单机执行:以MySQL为代表,这显然不够;
 ●  单机并行(SMP):以PostgreSQL为代表,不具备Scale Out能力,也可以排除;
 ●  分布式并行(MPP):以数据仓库和各种大数据框架为代表。

其中,MPP又可以根据能否做到Worker级的失败容忍,进一步细分成两种:分布式并行和批处理。这二者之间的性能差异已经很小了,更多的是看其他方面,例如:业务中是否需要做小时级的查询、生态是否完善等。

3320ddf5057f7773b15749c919c6dc27656906c7

从上表可以看出,Spark SQL足以胜任我们的需求。之所以没有选择Hive等,还有其他一些技术性、非技术性的考虑,不一定是绝对的,在这里也就不引战了。

五、DRDS HTAP的实践

阿里云DRDS只读实例中引入了Fireworks引擎,它是我们基于Apache Spark定制的分布式MPP引擎。

从接口上看,计算方式是对用户透明的,执行引擎自动根据用户输入的SQL来决定是否要进行分布式执行,如果需要分布式执行,则将执行计划下发给Fireworks集群,只需等待计算完成即可。

84398640d338ea50ac8a397c4cd889de1d57b997

DRDS HTAP并没有引入新的存储,而是利用了数据库本身的备库。不同于ETL等数据Pipeline,数据库主备之间的binlog同步速度非常快,通常在毫秒级别,足以满足绝大部分查询的实时性要求。从备库拉取数据,也是为了保障主库不会增加额外负担、对业务造成影响。

Q & A

Q:Optimizer这层如果收到复杂查询需要转到Spark计算的话是解析成Spark的logicplan吗?那如何跟Spark对接?

A:我们目前是直接使用的Spark SQL接口,因为不需要侵入到内部。这样可能造成的后果是Spark的优化器会再优化一次。不过我们的执行计划已经很具体了,通常Spark优化后依然和预期一样。


原文发布时间为:2018-11-5

本文作者:傅宇

本文来自云栖社区合作伙伴“DBAplus社群”,了解相关信息可以关注“DBAplus社群”。

【云栖快讯】一站式开发者服务,海量学习资源免费学  详情请点击

网友评论