Scala&Spark:回收SQL语句

Boe*_*ern 11 scala apache-spark apache-spark-sql

我花了很长时间来编写多个SQL查询,这些查询以前用于获取各种R脚本的数据.这就是它的工作原理

sqlContent = readSQLFile("file1.sql")
sqlContent = setSQLVariables(sqlContent, variables)
results = executeSQL(sqlContent)
Run Code Online (Sandbox Code Playgroud)

线索是,对于某些查询,需要先前查询的结果 - 为什么VIEW在数据库中创建s本身并不能解决这个问题.随着Spark 2.0我已经想出了一个办法,通过做到这一点

// create a dataframe using a jdbc connection to the database
val tableDf = spark.read.jdbc(...)
var tempTableName = "TEMP_TABLE" + java.util.UUID.randomUUID.toString.replace("-", "").toUpperCase
var sqlQuery = Source.fromURL(getClass.getResource("/sql/" + sqlFileName)).mkString
sqlQuery = setSQLVariables(sqlQuery, sqlVariables)
sqlQuery = sqlQuery.replace("OLD_TABLE_NAME",tempTableName)
tableDf.createOrReplaceTempView(tempTableName) 
var data = spark.sql(sqlQuery)
Run Code Online (Sandbox Code Playgroud)

但这是我非常愚蠢的意见.此外,更复杂的查询,例如,当前无法使用子查询因子的查询不起作用.有没有像重新实现的SQL代码到一个更强大的方式Spark.SQL使用代码filter($""),.select($"")等等.

总体目标是获得多个org.apache.spark.sql.DataFrames,每个s代表一个以前的SQL查询(总是几个JOINs,WITHs等)的结果.所以n查询导致n DataFrames.

有没有比提供的更好的选择?

设置:Win7工作站上的Hadoop v.2.7.3,Spark 2.0.0,Intelli J IDEA 2016.2,Scala 2.11.8,Testcluster

bar*_*lar 1

目前还不清楚您的要求是什么,但我认为您是说您有类似的疑问:

SELECT * FROM people LEFT OUTER JOIN places ON ...
SELECT * FROM (SELECT * FROM people LEFT OUTER JOIN places ON ...) WHERE age>20
Run Code Online (Sandbox Code Playgroud)

你会想要有效地声明和执行它

SELECT * FROM people LEFT OUTER JOIN places ON ...
SELECT * FROM <cachedresult> WHERE age>20
Run Code Online (Sandbox Code Playgroud)

为了实现这一点,我将增强输入文件,以便每个 sql 语句都有一个关联的表名,结果将存储在其中。

例如

PEOPLEPLACES\tSELECT * FROM people LEFT OUTER JOIN places ON ...
ADULTS=SELECT * FROM PEOPLEPLACES WHERE age>18
Run Code Online (Sandbox Code Playgroud)

然后像这样循环执行

parseSqlFile().foreach({case (name, query) => {
    val data: DataFrame = execute(query)
    data.createOrReplaceTempView(name)
}
Run Code Online (Sandbox Code Playgroud)

确保按顺序声明查询,以便创建所有必需的表。其他的则进行更多的解析并按依赖关系排序。

在 RDMS 中,我将这些表称为物化视图。即对其他数据(如视图)的转换,但结果会被缓存以供以后重用。