【问题标题】:I write an sparksql UDF with java but it seems that something goes wrong我用 java 在 spark sql UDF 中编写,但似乎出了点问题
【发布时间】:2018-01-10 15:29:46
【问题描述】:

我的项目的整个依赖如下代码:

<dependencies>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.11</artifactId>
        <version>2.1.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql_2.11</artifactId>
        <version>2.1.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-hive_2.11</artifactId>
        <version>2.1.2</version>
    </dependency>

</dependencies>

我想使用UDF 来计算两个输入日期字符串之间的时间间隔,格式为'yyyy-mm-ss HH:mm:ss.SSS'(例如,'2017-12-26 00:00 :02.044'),结果将加倍,精度为毫秒,例如,当我将“2017-12-26 00:00:02.044”、“2017-12-26 00:00:03.045”传递给@ 987654323@ 结果将是 1.001 秒然后附带 java 代码 sn -p:

import org.apache.commons.lang.StringUtils;
import org.apache.spark.sql.api.java.UDF2;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDistance implements UDF2<String,String,Double> {

    public Double call(String s, String s2) throws Exception {
        Double result=0D;
        if(StringUtils.isNotBlank(s)&&StringUtils.isNotBlank(s2)){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-ss HH:mm:ss.SSS");
            Date parse = sdf.parse(s);
            Date parse2=sdf.parse(s2);
            Long milisecond1= parse.getTime();
            Long milisecond2= parse2.getTime();
            Long abs = Math.abs(milisecond1 - milisecond2);
            result = (abs.doubleValue()) / 1000D;
        }
        return result;
    }
}

UDF的使用步骤如下:

  1. 添加 jar /home/hulk/learning/datedistance-1.0-SNAPSHOT.jar
  2. 创建临时函数 tmp_date_distance 为 'com.test.datedistance.DateDistance'
  3. 使用 sql 测试 UDF:
Select tmp_date_distance('2017-12-26 00:00:02.044','2017-12-26
00:00:03.045') from stg.car_fact_order where dt='2018-01-09' limit 1;

在那之后,我得到了以下提示:

Error in query: No handler for Hive UDF 'com.sqyc.datedistance.DateDistance'; line 1 pos 7

你能给我一些建议吗?

【问题讨论】:

    标签: java apache-spark apache-spark-sql user-defined-functions


    【解决方案1】:

    第二步不正确:

    创建临时函数 tmp_date_distance 为 'com.test.datedistance.DateDistance'

    Spark UDF 与 Hive 不兼容,应向其注册

    sqlContext.udf().register(name, object, type);
    

    或(2.0 或更高版本):

    spark.udf().register(name, object, type);
    

    但你不需要 udf:

    SELECT ABS(
           CAST(CAST('2017-12-26 00:00:02.044' AS TIMESTAMP) AS DOUBLE) - 
           CAST(CAST('2017-12-26 00:00:03.045' AS TIMESTAMP) AS DOUBLE) ) AS diff
    
    +-----------------+
    |             diff|
    +-----------------+
    |1.001000165939331|
    +-----------------+
    

    或四舍五入:

    SELECT ROUND(ABS(
           CAST(CAST('2017-12-26 00:00:02.044' AS TIMESTAMP) AS DOUBLE) - 
           CAST(CAST('2017-12-26 00:00:03.045' AS TIMESTAMP) AS DOUBLE)), 3) AS diff
    
    +-----+
    | diff|
    +-----+
    |1.001|
    +-----+
    

    【讨论】:

    • 我已经尝试了上面列出的所有方法,它们都很好用。非常感谢。
    • 如果语法CREATE TEMPORARY FUNCTION ...不是有效的Spark SQL,那么为什么提供它,为什么SQL处理器会成功执行语句?是否有其他有效的 CREATE TEMPORARY FUNCTION 使用可以实现上述目的,而无需用户编译 spark/scala 应用程序或使用 pyspark api?在 SQL 中有些事情更容易(想想你可以跳过的编译/部署步骤......),但只有当它有效时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-08
    • 2017-05-23
    • 1970-01-01
    • 2015-08-03
    相关资源
    最近更新 更多