#hive #函数
自定义函数开发和注册
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;public class ToUpperCaseUDF extends UDF {public Text evaluate(Text input) {if (input == null) {return null;}return new Text(input.toString().toUpperCase());}
}
编译和打包成jar
javac -cp $(hadoop classpath) ToUpperCaseUDF.java
jar cf to_uppercase.jar ToUpperCaseUDF.class
上传到HDFS
注册自定义函数
-- 创建临时函数(会话结束后失效)
CREATE TEMPORARY FUNCTION to_uppercase AS 'com.example.ToUpperCaseUDF';-- 或创建永久函数(需写入 Hive 元数据库)
CREATE FUNCTION to_uppercase AS 'com.example.ToUpperCaseUDF' USING JAR '/path/to/to_uppercase.jar';
使用:
SELECT to_uppercase(name) FROM users WHERE age > 30;
GenericUDF
普通UDF通常处理固定的输入输出类型,比如Text或IntWritable,而GenericUDF允许处理任意类型的参数和返回类型,这使得它在处理复杂数据结构时更加灵活。
- 动态类型支持:无需预先声明输入/输出类型,可自动适应不同数据类型(如
int
,string
,array
等)。 - 复杂逻辑处理:适合需要类型判断、多条件分支的场景(例如
IF
函数)。 - 元数据兼容:直接与 Hive 的元数据系统集成。
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFReturnType;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.TypeInfo;import java.util.List;public class DynamicAddUDF extends GenericUDF {@Overridepublic ObjectInspector initialize(ObjectInspector[] parameters) throws UDFArgumentException {// 验证参数数量(必须为2个)if (parameters.length != 2) {throw new UDFArgumentException("DynamicAddUDF requires exactly 2 arguments");}// 支持数值类型(int, double, long)和字符串相加TypeInfo typeInfo1 = parameters[0].getTypeInfo();TypeInfo typeInfo2 = parameters[1].getTypeInfo();// 检查是否为数值类型或字符串if (!(typeInfo1.getCategory() == TypeInfo.Category.NUMERIC ||typeInfo1.getCategory() == TypeInfo.Category.STRING)) {throw new UDFArgumentException("First argument must be numeric or string");}if (!(typeInfo2.getCategory() == TypeInfo.Category.NUMERIC ||typeInfo2.getCategory() == TypeInfo.Category.STRING)) {throw new UDFArgumentException("Second argument must be numeric or string");}// 返回值类型与第一个参数相同(如果两个参数都为数值,则统一为最大精度)return parameters[0];}@Overridepublic Object evaluate(DeferredObject[] arguments) throws HiveException {if (arguments[0].get() == null || arguments[1].get() == null) {return null;}ObjectInspector inspector1 = arguments[0].getObjectInspector();ObjectInspector inspector2 = arguments[1].getObjectInspector();// 获取原始值Object val1 = arguments[0].get();Object val2 = arguments[1].get();// 处理数值类型相加if (inspector1 instanceof PrimitiveObjectInspector &&inspector2 instanceof PrimitiveObjectInspector) {PrimitiveObjectInspector poi1 = (PrimitiveObjectInspector) inspector1;PrimitiveObjectInspector poi2 = (PrimitiveObjectInspector) inspector2;Class<?> clazz1 = poi1.getObjectClass();Class<?> clazz2 = poi2.getObjectClass();if (clazz1 == Long.class && clazz2 == Long.class) {return Long.valueOf(val1.toString()) + Long.valueOf(val2.toString());} else if (clazz1 == Double.class && clazz2 == Double.class) {return Double.valueOf(val1.toString()) + Double.valueOf(val2.toString());} else if (clazz1 == Integer.class && clazz2 == Integer.class) {return Integer.valueOf(val1.toString()) + Integer.valueOf(val2.toString());}}// 处理字符串拼接if (inspector1.getTypeInfo().getCategory() == TypeInfo.Category.STRING &&inspector2.getTypeInfo().getCategory() == TypeInfo.Category.STRING) {return val1.toString() + val2.toString();}throw new HiveException("Unsupported operand types for DynamicAddUDF");}@Overridepublic String getDisplayString(String[] children) {return "DynamicAddUDF(" + children[0] + ", " + children[1] + ")";}
}
方法 | 作用 |
---|---|
initialize | 初始化函数,用于参数校验和返回类型确定(通过 ObjectInspector )。 |
evaluate | 核心逻辑实现,动态处理不同类型的参数。 |
getDisplayString | 定义函数在 Hive SQL 中的显示名称(可选)。 |