云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

腾讯云_好用云主机_高性价比

小七 141 0

Spark SQL即将实现令人兴奋的性能改进

随着apachespark1.0的推出,我们将对Spark项目的下一个主要计划进行预览。今天,Spark最活跃的组件是Spark SQL—一个与核心Spark API交互操作的紧密集成的关系引擎。sparksql是在spark1.0中发布的,它将为Shark的未来版本提供一个轻量级、灵活的执行后端。在这篇文章中,我们将重点介绍一些与Scala和Spark紧密集成的方法,这些方法为我们提供了强大的工具来优化sparksql的查询执行。这篇文章概述了最令人兴奋的特性之一,动态代码生成,并解释了使用一个著名的基准测试TPC-DS的查询,这个特性可以提供什么样的性能提升。作为基准,我们将性能与当前的Shark版本进行比较。我们很高兴地报告,在这些情况下,sparksql的性能优于Shark,有时甚至是惊人的。请注意,以下测试是在sparksql的一个开发分支上运行的,它包括几个新的性能特性。虽然这只是来自TPC-DS基准测试的几个查询,但我们计划在未来发布更全面的结果。现在,我们已经看到了事情的发展方向,让我们深入了解我们计划如何实现目标的技术细节。这是关于sparksql中的优化的一系列博客文章中的第一篇。运行时字节码生成数据库需要执行的更昂贵的操作之一是查询中表达式的求值。JVM的内存模型会显著增加此评估的成本。为了理解为什么会出现这种情况,让我们看一个具体的例子:从表中选择a+b在上面的查询中,有一个表达式将为表的每一行求值,即a+b。通常,该表达式将由表达式树表示。树的每个节点都由一个对象表示,该对象的求值方法知道如何计算给定输入行的表达式的结果。在本例中,当对Add对象调用evaluate方法时,它将依次对其每个子对象调用evaluate,然后计算返回值的总和。从性能角度来看,这种方法有什么问题?实际上,性能损失来自于这种解释执行的几个细节:虚函数调用-每次对给定的表达式对象调用evaluate时,都会调用一个虚函数。这些类型的函数调用会破坏处理器中的管道,从而减慢执行速度。当表达式非常复杂时,问题会恶化,比如TPC-DS基准中的表达式。基元值的装箱-由于evaluate需要能够根据表达式(Integer、String、Float等)返回许多不同类型的值,因此它需要一个通用的返回类型Object。这意味着需要为评估的每个步骤分配一个额外的对象。虽然现代jvm在廉价地分配短期对象方面已经变得更好,但这一成本确实会增加。泛型成本-这些表达式树需要能够处理许多不同的数据类型。但是,例如,添加两个整数所需的实际函数与添加两个双精度数所需的函数不同。这种泛型意味着求值代码通常需要额外的if语句,这些语句基于正在处理的数据类型进行分支。总之,上述问题会导致查询执行时间的显著增加。幸运的是,还有另一种方法!在sparksql的一个开发分支中,我们实现了一个表达式计算器的版本,它为每个查询动态生成自定义字节码。虽然这样的生成听起来像是一个困难的任务,但是使用scala2.10中的一个新特性,运行时反射,其实很容易实现。在较高的层次上,字节码生成意味着,Spark SQL将在运行时创建新的类,这些类的自定义代码类似于以下内容:值a:Int=输入行.getInt(0)值b:Int=输入行.getInt(一)val结果:Int=a+b结果流.setInt(0,结果)与解释的求值相比,生成的代码处理原始值(因此不分配任何对象),并且不包含额外的函数调用。使用拟迹虽然sparksql不是执行查询执行的动态代码生成的唯一系统,但Scala反射的使用大大简化了实现,使其更易于扩展和改进。这个功能的关键是Scala中的一个新特性,称为quasiqueotes。quasiqueotes使得在运行时构建Scala代码树变得很容易,而不必手工构建复杂的ast。要使用quasiquote,只需在Scala中的字符串前面加上字母"q"。在这样做时,告诉Scala编译器将字符串的内容视为代码,而不是文本。还可以使用$variables将不同的代码片段拼接在一起。例如,生成上述加法表达式的代码可以简单地表示为:def generateCode(e:表达式):Tree=e匹配{大小写属性(序数)=&>问"输入行.getInt($序数)"case Add(左,右)=&>q"{val leftResult=${generateCode(left)}val rightResult=${generateCode(右)}leftResult+rightResult}"""}实际上,生成的代码稍微复杂一些,因为它还需要处理null值。如果您想查看我们的示例表达式生成的代码的完整版本,可以在这里找到它。结论动态代码生成只是冰山一角,我们还有很多改进,包括:改进的Parquet集成、自动查询半结构化数据(如JSON)的能力,以及对sparksql的JDBC访问。请继续关注我们正在进行的其他优化以激发SQL的更多更新!免费试用Databricks。今天就开始吧