我们需要在Spark SQL中转换和执行执行hive查询。查询涉及 2 个表之间的联接。我们将创建一个数据帧,然后在它之上创建 Sparksql 查询。请查找示例配置单元查询以及转换后的查询。
------配置单元查询
select a.col1,a.col2,a.col3,b.col4,b.col5,b.col6.b.col7
from table1 a left outer join table2 b
on a.col3=b.col3
-----Spark SQL
import org.apache.spark.sql.hive.HiveContext
val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
val q1=hivecontext.sql("select col1,col2,col3,col4 from table1");
val q2=hivecontext.sql("select col3,col5,col6,col7 from table2");
val q3=q1.join(q2,q1("col3")===q2("col3"));
但是我们也可以在单个数据框中执行整个查询,如下所示
**
val q5=hivecontext.sql("select
a.col1,a.col2,a.col3,b.col4,b.col5,b.col6.b.col7
from table1 a left outer join table2 b
on a.col3=b.col3")**
我想知道在这种情况下我们更好地使用两种方法(单数据帧与多数据帧(中的哪一种,以及在性能和可读性等各种参数上优于另一种方法的优势。
第二种方法似乎在各个方面都是明智的
- 在 Hive 数据上运行 SQL 时,HiveContext 将在 Hive 中运行查询,并将结果元数据返回到 Spark。所以 Spark 只需要存储生成的元数据集。但在上述情况下,它必须将蜂巢中的所有数据存储到其RDD中。
- 维护单个RDD也有助于优化DAG。
- 如果你作为单个查询运行,即使是Spark catalyst也会进一步优化它。
- 它的可读性看起来更好。
这两种方法是相同的。从性能的角度来看,这并不重要。催化剂优化器将为这两个查询创建相同的物理计划。
但是,现在还有其他方面需要考虑。编写 SQL 查询通常很容易,但是您丢失了编译时类型检查。如果 SQL 中有拼写错误或列名不正确,则除非在群集上运行该列名,否则无法找到。但是,如果使用数据帧操作,则代码不会编译。因此,它有助于提高编码速度。
但是,使用数据帧 API 编写复杂的 SQL 也不是一件容易的事。因此,通常我使用操作相对简单的数据帧API,并使用SQL进行复杂查询。