利用Apache Spark SQL和DataFrames扩展关系数据库
无论怎样大肆宣传NoSQL数据库的出现,关系数据库都还将继续存在。原因很简单,关系数据库强制执行基本的结构和约束,并提供了很好的声明式语言来查询数据(我们都喜欢它):SQL!
但是,规模一直是关系数据库的问题。21世纪的大多数企业都拥有丰富的数据存储和仓库,并希望最大限度地利用大数据来获得可操作的洞见。关系数据库可能很受欢迎,但除非我们投资了适当的大数据管理策略,否则不能很好地对它们进行扩展。这包括考虑潜在的数据源,数据量,约束,模式,ETL(提取 - 转换 - 加载),访问和查询模式等等!
本文将介绍在关系数据库的强大功能方面取得的一些优秀进展,而对于“大规模”,会介绍Apache Spark – Spark SQL和DataFrames 中的一些新组件。最值得注意的是,将涵盖以下主题:
- 关系数据库扩展的动机和挑战
- 了解Spark SQL和DataFrames
- 目标
- 架构和功能
- 性能
人们努力地工作并投入时间在ApacheShark中构建新组件,我们关注他们的主要挑战和动机,以便能够大规模执行SQL。我们还将研究Spark SQL和DataFrames的主要体系结构、接口、功能和性能基准。在本文最后,最重要的一点,我们将介绍一个分析入侵攻击的真实案例研究,基于KDD 99 CUP数据,利用Spark SQL和DataFrames,通过Databricks云平台来平衡从而实现Spark。
为大数据而扩展关系数据库的动机和挑战
关系数据存储易于构建和查询。此外,用户和开发人员通常更喜欢用类似人类的可读语言(如SQL)编写易于解释的声明式查询。然而,随着数据的数量和多样性的增加,关系方法的伸缩性不足以构建大数据应用程序和分析系统。以下是一些主要挑战:
- 处理不同类型数据源,可以是结构化、半结构化和非结构化的;
- 建立各种数据源之间的ETL管道,这可能导致要开发大量特定的自定义代码,随着时间的推移会增加技术债务
- 能够执行基于传统商业智能(BI)的分析和高级分析(机器学习、统计建模等),后者在关系系统中执行肯定具有挑战性
大数据分析并不是昨天才发明的!我们在Hadoop和MapReduce范式方面取得了成功,这很厉害但进展太慢,它为用户提供了一个低级的、程序化的编程接口,需要人们编写大量代码来进行非常简单的数据转换。然而,自从Spark的发布,它真正改变了大数据分析的方式,不需要再把重点放在内存计算、容错、高级抽象和易用性上。
从那时起,一些框架和系统,如Hive、Pig和Shark(演变成Spark SQL),为大数据存储提供了丰富的关系接口和声明式查询机制。挑战在于,这些工具要么是基于关系的,要么是基于过程的,但是鱼和熊掌无法两者兼得。
然而,在现实世界中,大多数数据分析管道可能涉及到关系代码和过程代码的组合。如果强迫用户选择其中一个会最终让事情变得复杂,并增加用户在开发、构建和维护不同应用程序和系统方面的工作量。Apache Spark SQL建立在前面提到的SQL on Spark(称为Shark)的基础上,它不强制要求用户在关系API或过程API之间进行选择,而是试图让用户无缝地混合使用它们,来对大数据进行大规模的数据查询、检索和分析。
了解Spark SQL和DataFrame
Spark SQL本质上试图用两个主要组件弥合我们之前提到的两个模型(关系模型和过程模型)之间的差距。
- Spark SQL提供了一个DataFrame API,可以对外部数据源和Spark的内置分布式集合进行大规模的关系操作!
- 为了支持大数据中各种各样的数据源和算法,Spark SQL引入了一种名为Catalyst的新型可扩展优化器,可以轻松地为机器学习等高级分析添加数据源、优化规则和数据类型。
从本质上讲,Spark SQL利用Spark的强大功能在大数据上大规模地执行分布式的、健壮的内存计算。Spark SQL提供了最先进的SQL性能,并且兼容Apache Hive(一种流行的大数据仓库框架)支持的所有现有结构和组件,包括数据格式、用户定义函数(UDF)和Metastore。除此之外,它还有助于从大数据源和企业数据仓库(如JSON,Hive,Parquet等)中提取各种数据格式,并执行关系和过程操作的组合,以实现更复杂的高级分析。
目标
让我们看一下有关Spark SQL的一些有趣的事实,包括它的使用、采用和目标,其中一些我将再次从“ Spark中的关系数据处理 ”的优秀原始论文中复制过来。Spark SQL于2014年5月首次发布,现在可能是Spark中最活跃的组件之一。Apache Spark绝对是大数据处理最活跃的开源项目,有数百个贡献者。
除了作为一个开源项目,Spark SQL已经开始得到主流行业的采用,并部署在了非常大规模的环境中。Facebook有一个关于“ Apache Spark @Scale:一个 60TB+ 的生产用例 ” 的优秀案例研究,他们正在为实体排名做数据准备,其Hive的工作过去需要几天时间并面临许多挑战,但Facebook成功地使用Spark进行扩展并提高了性能。接下来让我们看看他们在这次旅程中遇到的有趣挑战!
另一个有趣的事实是,三分之二的Databricks云(运行Spark的托管服务)客户在其他编程语言中使用了Spark SQL。在本系列的第二部分中,我们还将展示使用Spark SQL on Databricks的实际案例研究。
Spark SQL的主要目标是由它的创建者所定义的:
- 无论是在Spark程序(在本机RDD上)还是在外部数据源上,都使用对程序员友好的API来支持关系处理
- 使用已建立的DBMS技术提供高性能
- 轻松支持新的数据源,包括半结构化数据和易于查询联合的外部数据库
- 使用高级分析算法(如图形处理和机器学习)进行扩展
架构和功能
现在我们来看看Spark SQL和DataFrames的主要功能和架构。这里需要牢记围绕着Spark生态系统的一些关键概念,随着时间的推移这个生态一直在不断发展。
RDD(弹性分布式数据集)可能是Spark所有成功案例背后的最大贡献者。它基本上是一种数据结构,或者更确切地说是分布式存储器的抽象,它允许程序员在大型分布式集群上执行内存计算,同时保留容错等方面的特性。还可以并行化大量计算和转换,并跟踪转换的整个过程,这有助于有效地重新计算丢失的数据。此外,Spark使用驱动程序和执行程序的概念,如下图所示。
通常可以从文件、数据库读取数据,并行化现有集合甚至转换来创建RDD。通常,转换是将数据转换为不同方面和维度的操作,具体取决于我们想要整理和处理数据的方式。它们也会被延迟地评估,这意味着即使定义了转换,在执行动作之前也不会计算结果,通常需要将结果返回到驱动程序(然后它会计算所有应用的转换!)。
既然已经了解了Spark工作原理的架构,那么让我们更深入地了解Spark SQL。通常,Spark SQL在Spark之上作为库运行,正如我们在图中看到的那样,它覆盖了Spark生态系统。下图详细介绍了Spark SQL的典型体系结构和接口。
该图清楚地显示了各种SQL接口,通过JDBC/ODBC或命令行控制台来访问,集成到Spark支持的编程语言中的DataFrame API(我们将使用Python)。DataFrame API非常强大,允许用户最终混合程序代码和关系代码!诸如UDF(用户定义函数)之类的高级函数可以在SQL中使用,BI工具也可以使用它。
Spark DataFrames非常有趣,可以帮助我们利用Spark SQL的强大功能,并根据需要结合其过程式范例。Spark DataFrame基本上是具有相同模式的行(行类型)的分布式集合,它基本上是被组织成一些命名列的Spark数据集。这里需要注意的是,数据集是DataFrame API的扩展,它提供了一种*类型安全的、面向对象的编程接口。*它们仅在Java和Scala中可用,因此我们将专注于DataFrame。
DataFrame等同于关系数据库中的表(但在引擎盖下具有更多优化),并且还可以以类似于Spark(RDD)中的“本机”分布式集合的方式进行操作。Spark DataFrames有一些有趣的属性,例如:
- 与RDD不同,DataFrame通常会跟踪schema并支持各种关系操作,从而实现更优化的执行。
- DataFrame可以通过表来构建,就像大数据基础结构中现有的Hive表一样,甚至可以从现有的RDD来构建。
- DataFrames可以使用直接SQL查询操作,也可以使用DataFrame DSL(特定领域语言),以及使用各种关系运算符和变换器,例如where和groupBy。
- 此外,每个DataFrame也可以被视为行对象的RDD,允许用户调用过程化的Spark API,例如map。
- 最后,与传统的Dataframe API(Pandas)不同,Spark DataFrames具有延迟性,因为每个DataFrame对象都代表一个逻辑计划来计算数据集,但在用户调用特殊的“输出操作”(如save)之前,不会执行任何操作。
这应该让您对Spark SQL、数据框架、基本特性、概念、体系结构和接口有了足够的了解。下面让我们看一下性能基准来完成这一部分。
性能
在没有正确优化的情况下发布一个新特性是致命的,构建Spark的人做了大量的性能测试和基准测试!让我们看看一些有趣的结果,下面描述了展示一些结果的第一个图。
在这些实验中,他们使用AMPLab的大数据基准测试比较了Spark SQL与Shark和Impala的性能,后者使用了Pavlo等人开发的网络分析工作负载。基准测试包含带不同参数的四种类型查询,这些查询具有执行扫描、聚合、连接和基于UDF的MapReduce作业。使用列式Parquet格式压缩后,数据集包含了110GB的数据。我们看到,在所有查询中,Spark SQL比Shark快得多,通常与Impala竞争。Catalyst优化器负责这个压缩,降低了CPU开销(后面会简要介绍这一点)。此功能使Spark SQL在许多查询中与基于C ++和LLVM的Impala引擎竞争,与Impala的最大差距在于Query 3a中Impala选择更好的join计划,查询的选择性使得其中一个表非常小。
下面的图表显示了DataFrames和常规Spark API以及Spark + SQL的一些性能基准。
Spark DataFrames vs. RDD 和 SQL
最后,下图显示了不同语言中DataFrames与RDD的一个很好的基准测试结果,从而为优化的DataFrames提供了一个有趣的视角。
比较Spark DataFrames 和 RDD
性能秘诀:Catalyst优化器
为什么Spark SQL如此快速和优化?原因是因为新的可扩展优化器Catalyst,基于scala中的函数式编程结构。虽然不会在这里详细介绍Catalyst,但值得一提的是,它有助于优化DataFrames的操作和查询。
Catalyst的可扩展设计有两个目的:
- 可以轻松地为Spark SQL添加新的优化技术和功能,尤其是解决大数据、半结构化数据和高级分析方面的各种问题
- 易于优化器的扩展 – 例如,通过添加定制于数据源的规则,可以将过滤或聚合推送到外部存储系统,或支持新的数据类型
Catalyst支持基于规则和基于成本的优化。虽然可扩展优化器在过去已经被提出,但它们通常需要一种复杂的特定于域的语言来指定规则。通常,这会导致显著的学习曲线和维护负担。相比之下,Catalyst使用Scala编程语言的标准特性,例如模式匹配,让开发人员使用完整的编程语言,同时仍然使规则易于指定。
Catalyst的核心包含了一个通用库,用于表示树状结构并应用规则来操作它们。在这个框架的顶部,包含关系查询处理(例如,表达式、逻辑查询计划)的库,以及处理查询执行的不同阶段的若干规则:分析、逻辑优化、物理规划和代码生成,以将查询的部分编译成Java字节码。
关于作者
Dipanjan(DJ)Sarkar – Dipanjan(DJ)Sarkar是RedHat的数据科学家、出版作家、顾问和培训师。他曾在多家创业公司以及英特尔等财富500强公司做过顾问和合作。他主要致力于利用数据科学、机器学习和深度学习来构建大规模智能系统。他拥有数据科学和软件工程专业的技术硕士学位。他也是自学者和大规模开放在线课程的*支持者。
查看英文原文:Scaling relational databases with Apache Spark SQL and DataFrames