spark sql是spark中处理结构化数据的模块。与基础的spark rdd api不同,spark sql的接口提供了更多关于数据的结构信息和计算任务的运行时信息。在spark内部,spark sql会能够用于做优化的信息比rdd api更多一些。spark sql如今有了三种不同的api:sql语句、dataframe api和最新的dataset api。不过真正运行计算的时候,无论你使用哪种api或语言,spark sql使用的执行引擎都是同一个。这种底层的统一,使开发者可以在不同的api之间来回切换,你可以选择一种最自然的方式,来表达你的需求。
本文中所有的示例都使用spark发布版本中自带的示例数据,并且可以在spark-shell、pyspark shell以及sparkr shell中运行。
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_scala_0"><b>scala</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_java_0"><b>java</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_python_0"><b>python</b></a>
除了sqlcontext之外,你也可以创建hivecontext,hivecontext是sqlcontext 的超集。
除了sqlcontext的功能之外,hivecontext还提供了完整的hiveql语法,udf使用,以及对hive表中数据的访问。要使用hivecontext,你并不需要安装hive,而且sqlcontext能用的数据源,hivecontext也一样能用。hivecontext是单独打包的,从而避免了在默认的spark发布版本中包含所有的hive依赖。如果这些依赖对你来说不是问题(不会造成依赖冲突等),建议你在spark-1.3之前使用hivecontext。而后续的spark版本,将会逐渐把sqlcontext升级到和hivecontext功能差不多的状态。
spark.sql.dialect选项可以指定不同的sql变种(或者叫sql方言)。这个参数可以在sparkcontext.setconf里指定,也可以通过 sql语句的set key=value命令指定。对于sqlcontext,该配置目前唯一的可选值就是”sql”,这个变种使用一个spark sql自带的简易sql解析器。而对于hivecontext,spark.sql.dialect 默认值为”hiveql”,当然你也可以将其值设回”sql”。仅就目前而言,hivesql解析器支持更加完整的sql语法,所以大部分情况下,推荐使用hivecontext。
以下是一个从json文件创建dataframe的小栗子:
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_scala_1"><b>scala</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_java_1"><b>java</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_python_1"><b>python</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_r_1"><b>r</b></a>
这里我们给出一个结构化数据处理的基本示例:
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_scala_2"><b>scala</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_java_2"><b>java</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_python_2"><b>python</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_r_2"><b>r</b></a>
sqlcontext.sql可以执行一个sql查询,并返回dataframe结果。
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_scala_3"><b>scala</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_java_3"><b>java</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_python_3"><b>python</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_r_3"><b>r</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_scala_4"><b>scala</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_java_4"><b>java</b></a>
spark sql有两种方法将rdd转为dataframe。
1. 使用反射机制,推导包含指定类型对象rdd的schema。这种基于反射机制的方法使代码更简洁,而且如果你事先知道数据schema,推荐使用这种方式;
2. 编程方式构建一个schema,然后应用到指定rdd上。这种方式更啰嗦,但如果你事先不知道数据有哪些字段,或者数据schema是运行时读取进来的,那么你很可能需要用这种方式。
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_scala_5"><b>scala</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_java_5"><b>java</b></a>
<a href="http://spark.apache.org/docs/latest/sql-programming-guide.html#tab_python_5"><b>python</b></a>
spark sql的scala接口支持自动将包含case class对象的rdd转为dataframe。对应的case class定义了表的schema。case class的参数名通过反射,映射为表的字段名。case class还可以嵌套一些复杂类型,如seq和array。rdd隐式转换成dataframe后,可以进一步注册成表。随后,你就可以对表中数据使用sql语句查询了。