从Impala迁移到SparkSQL时,Impala内置函数不可用

时间:2016-12-21 21:43:09

标签: apache-spark pyspark apache-spark-sql impala

我在Impala中使用内置函数,如:

type AssignedTestType

现在我正在迁移到SparkSQL(在Jupyter Notebook中使用pyspark):

select id, parse_url(my_table.url, "QUERY", "extensionId") from my_table

但是,我收到以下错误:

my_table.select(my_table.id.cast('string'), parse_url(my_table.url.cast('string'), "QUERY", "extensionId")).show()

下面也尝试过:

NameError: name 'parse_url' is not defined

但所有my_table.registerTempTable("my_table") sqlContext.sql("select id, url, parse_url(url, 'QUERY', 'extensionId') as new_url from my_table").show(100) 都变为new_url

知道我错过了什么吗?此外,人们将如何处理这样的问题?谢谢!

1 个答案:

答案 0 :(得分:1)

一些遗漏的部分:

  • 您无法使用Spark执行Impala功能。
  • 有一个Hive UDF具有相同的名称和语法,可以与Spark一起使用,但它没有本机实现和函数包装器。这就是为什么可以使用带有Hive支持的HiveContext / SparkSession使用SQL调用它。

一般来说它应该可以正常工作:

spark.sql("""SELECT parse_url(
    'http://example.com?extensionId=foo', 'QUERY', 'extensionId'
)""").show()
+-----------------------------------------------------------------+
|parse_url(http://example.com?extensionId=foo, QUERY, extensionId)|
+-----------------------------------------------------------------+
|                                                              foo|
+-----------------------------------------------------------------+

NULL输出表示无法匹配给定的部分:

spark.sql("""SELECT parse_url(
    'http://example.com?bar=foo', 'QUERY', 'extensionId'
)""").show()
+---------------------------------------------------------+
|parse_url(http://example.com?bar=foo, QUERY, extensionId)|
+---------------------------------------------------------+
|                                                     null|
+---------------------------------------------------------+

您可以使用UDF获得类似的结果,但速度会明显变慢。

from typing import Dict
from urllib.parse import parse_qsl, urlsplit
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType, MapType

def parse_args(col: str) -> Dict[str, str]:
    """
    http://stackoverflow.com/a/21584580/6910411
    """
    try:
        return dict(parse_qsl(urlsplit(col).query))
    except:
        pass

parse_args_ = udf(parse_args, MapType(StringType(), StringType()))

将数据定义为:

df = sc.parallelize([
    ("http://example.com?bar=foo", ),
    ("http://example.com?extensionId=foo", ),
]).toDF(["url"])

可以按如下方式使用:

df.select(parse_args_("url")["extensionId"]).show()

结果为:

+----------------------------+
|parse_args(url)[extensionId]|
+----------------------------+
|                        null|
|                         foo|
+----------------------------+