【Apache Doris】自定义函数之 JAVA UDF 详解
【Apache Doris】自定义函数之 JAVA UDF 详解
- 一、背景说明
- 二、原理简介
- 三、环境信息
- 3.1 硬件信息
- 3.2 软件信息
- 四、IDE准备
- 五、JAVA UDF开发流程
- 5.1 源码准备
- 5.1.1 pom.xml
- 5.1.2 JAVA代码
- 5.2 mvn打包
- 5.2.1 clean
- 5.2.2 package
- 5.3 函数使用
- 5.3.1 upload
- 5.3.2 使用
- 六、注意事项
- 七、总结
一、背景说明
UDF 主要适用于,用户需要的分析能力 Doris 并不具备的场景。用户可以自行根据自己的需求,实现自定义的函数,并且通过 UDF 框架注册到 Doris 中,来扩展 Doris 的能力,并解决用户分析需求。
UDF 能满足的分析需求主要分为两种(本文中的 UDF 指的是二者的统称):
- UDF(User Defined Function): 用户自定义函数,这种函数会对单行进行操作,并且输出单行结果。当用户在查询时使用 UDF ,每行数据最终都会出现在结果集中。典型的 UDF 比如字符串操作 concat() 等。
- UDAF(User-Defined Aggregate Functions): 用户自定义的聚合函数,这种函数对多行进行操作,并且输出单行结果。当用户在查询时使用 UDAF,分组后的每组数据最后会计算出一个值并展结果集中。典型的 UDAF 比如集合操作 sum() 等。一般来说 UDAF 都会结合 group by 一起使用。
正式推出Java UDF 之前,Apache Doris提供了原生 UDF即C++ UDF 。由于是使用 C++ 来编写的,执行效率高、速度更快,但是在实际使用中也会存在一些问题:
- 跟 Doris 代码耦合度高,需要自己打包编译 Doris 源码
- 只支持 C++ 语言并且 UDF 代码出错会影响 Doris 集群稳定性
- 对于只熟悉 Hive和Spark 等大数据组件的用户有一定使用门槛
针对以上问题,Apache Doris 在1.2.0版本中正式推出全新的Java UDF ,让用户可以更便捷高效地开发和迁移UDF。

二、原理简介
众所周知,Doris的FE主要由JAVA编写、而BE是由C++编写。因此,如果需要C++编写的BE与JAVA UDF联动,那么必然需要借助网络通信或JNI(Java Native Interface):
- 网络通信:可以跨语言交互,但是会带来网络传输等额外的性能开销,PASS。
- JNI:用于在Java程序中调用本地(C/C++)代码。通过JNI,可以将C++代码编译成动态链接库,然后在Java程序中加载该动态链接库,并通过JNI接口进行函数调用和数据传递。
JNI调用需要进行Java与本地代码之间的切换和数据转换,这也会带来一定的性能开销,如果频繁的JNI调用还可能会对应用的性能产生不利影响。那么Doris该如何设计 Java UDF 呢?
- 开发规范:制定一些开发规范让流程有序且容错率高,例如UDF 类必须具有 evaluate 方法,并且必须是 Public 和 Non-Static 的。
- 重用JVM:BE 会创建或重用一个 JVM 来调用真正的 Java UDF,保证效率的同时让资源利用率最大化。
- 向量化执行:执行时是向量化的,可以实现一次执行多行数据只调用一次 JNI,给用户带来更好的性能体验。
下面,就来一起体验下Apache Doris 的 Java UDF吧。
三、环境信息
3.1 硬件信息
- CPU:48C
- 内存:256G
3.2 软件信息
- 系统:CentOS
- JAVA版本:1.8
- Apache Doris版本:2.1 rc01
四、IDE准备
直接IntelliJ IDEA:

五、JAVA UDF开发流程
Java UDF 使用起来非常简单。只需要按规范开发完并通过mvn打成jar包后,在 Apache Doris 内注册一下,即可调用 jar 包来实现 UDF 逻辑:

5.1 源码准备
5.1.1 pom.xml
仅补齐dependencies和build部分。
<dependencies><dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>2.3.5</version><exclusions><exclusion><groupId>org.pentaho</groupId><artifactId>*</artifactId></exclusion></exclusions></dependency></dependencies><build><finalName>doris_java_udf</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.2</version><configuration><archive><manifest><mainClass>org.apache.doris.udf.AddOne</mainClass></manifest></archive></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.3.0</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifest><mainClass>org.apache.doris.udf.AddOne</mainClass></manifest></archive></configuration><executions><execution><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin></plugins></build>
5.1.2 JAVA代码
直接使用官方的demo:
https://github.com/apache/doris/blob/master/samples/doris-demo/java-udf-demo/src/main/java/org/apache/doris/udf/AddOne.java
package org.apache.doris.udf;import org.apache.hadoop.hive.ql.exec.UDF;public class AddOne extends UDF {public Integer evaluate(Integer value) {return value == null? null: value + 1;}
}
5.2 mvn打包
5.2.1 clean
先clean清理target。

5.2.2 package
再package打新包。

5.3 函数使用
5.3.1 upload
打好的jar包(即doris_java_udf.jar,不需要传依赖jar包),可以以两种方式存放:
- 服务化:多机环境时,也可以使用http的方式下载jar包
- 本地路径:FE、BE节点都要放置,并且都有权限访问的路径。
本文选择本地路径的方式演练:

5.3.2 使用
-- udf
-- 查看
show full functions;-- 删除
DROP FUNCTION add_one(int);-- 创建
-- 函数名可自定义
CREATE FUNCTION add_one(int) RETURNS int PROPERTIES (-- 文件路径,可本地或http"file"="file:///udf/doris_java_udf.jar",-- extends UDF 的类名"symbol"="org.apache.doris.udf.AddOne",-- 可选,如果在计算中对出现的NULL值有特殊处理,确定结果中不会返回NULL,可以设为false"always_nullable"="true",-- 默认为 Native,使用 Java UDF时传 JAVA_UDF"type"="JAVA_UDF"
)-- 测试,在传参基础上+1,如果非数字或者null则返回null
select add_one('0');

六、注意事项
虽然JAVA UDF整起来非常顺畅方便,但实际生产使用中有如下一些官方提醒:
- 不支持复杂数据类型(HLL,Bitmap)。
- 当前允许用户自己指定JVM最大堆大小,BE配置项是jvm_max_heap_size。配置项在BE安装目录下的be.conf全局配置中,默认512M,如果需要聚合数据,建议调大一些,增加性能,减少内存溢出风险。
- char类型的udf在create function时需要使用String类型。
- 由于jvm加载同名类的问题,不要同时使用多个同名类作为udf实现,如果想更新某个同名类的udf,需要重启be重新加载classpath。
七、总结

Java UDF相对1.2之前的C++ UDF而言,使用起来会更加便捷高效,而且更利于Hive/Spark的UDF jar包迁移,并且Doris团队对其底层实现流程进行了一系列性能优化,面面俱到。各位看官大可放心使用!
相关文章:
【Apache Doris】自定义函数之 JAVA UDF 详解
【Apache Doris】自定义函数之 JAVA UDF 详解 一、背景说明二、原理简介三、环境信息3.1 硬件信息3.2 软件信息 四、IDE准备五、JAVA UDF开发流程5.1 源码准备5.1.1 pom.xml5.1.2 JAVA代码 5.2 mvn打包5.2.1 clean5.2.2 package 5.3 函数使用5.3.1 upload5.3.2 使用 六、注意事…...
BMS电池管理系统带充放电控制过流过压保护
2.4G无线采集BMS开发板(主从一体) 全新升级 (赠送上位机源码TTL 上位机,可以改成自己想要的界面) 12串电池TTL上位机 CAN通信上位机源码有偿开源,供项目二次开发。 增加STM32平台 USB转TTL通信 CAN通信 增加…...
在Linux中以后台静默运行Java应用程序
在Linux系统上运行Java应用程序时,有时我们希望将其设置为后台运行,而关闭终端窗口时不会影响进程的执行。在本文中,我们将介绍几种实现这一目标的方法。 1. 使用nohup命令 nohup是一个用于在后台运行进程的命令,而且关闭终端窗…...
k8s---Pod的生命周期
Pod是什么? pod是k8s中最小的资源管理组件。 pod也是最小化运行容器化应用的资源管理对象。 pod是一个抽象的概念,可以理解为一个或者多个容器化应用的集合 在一个pod当中运行一个容器是最常用的方式 在一个pod当中可以同时运行多个容器,…...
CSS animation动画和关键帧实现轮播图效果HTML
CSS animation动画和关键帧实现轮播图效果HTML 这轮播图效果使用h5和css3实现效果,不需要js控制,但是其中的缺点就是不能使用鼠标进行切换效果。 具有代码如下 <!DOCTYPE html> <html lang"en"><head><meta charset&quo…...
Unity之键盘鼠标的监控
小编最近在玩大表哥2,通过 W、A、S、D 来移动亚瑟,鼠标左键来不吃牛肉 我们都知道玩家通过按键鼠标来控制游戏人物做出相应的行为动作,那在Unity引擎里是怎么知道玩家是如何操作的呢?本篇来介绍Unity是怎样监控键盘和鼠标的。 首先…...
C# windows服务程序开机自启动exe程序
我们使用传统的Process.Start(".exe")启动进程会遇到无法打开UI界面的问题,尤其是我们需要进行开启自启动程序设置时出现诸多问题,于是我们就想到采用windows服务开机自启动来创建启动一个新的exe程序,并且是显式运行。 首先是打开…...
【SpringMVC】常用注解
什么是MVC? MVC是一种程序分层开发模式,分别是Model(模型),View(视图)以及Controller(控制器)。这样做可以将程序的用户界面和业务逻辑分离,使得代码具有良好…...
关于曲率、曲率半径和曲率圆,看这几篇文章就够啦
关于曲率、曲率半径和曲率圆的内容,是考研数学数学一和数学二大纲中明确要求掌握的内容,但这部分内容在很多教材教辅以及练习题中较少涉及。在本文中,荒原之梦考研数学网就为大家整理了曲率、曲率半径和曲率圆方程相关的概念、基础知识以及练…...
java面试题-Spring常见的异常类有哪些?
远离八股文,面试大白话,通俗且易懂 看完后试着用自己的话复述出来。有问题请指出,有需要帮助理解的或者遇到的真实面试题不知道怎么总结的也请评论中写出来,大家一起解决。 java面试题汇总-目录-持续更新中 NullPointerException&…...
数据库选择题 (期末复习)
数据库第一章 概论简答题 数据库第二章 关系数据库简答题 数据库第三章 SQL简答题 数据库第四第五章 安全性和完整性简答题 数据库第七章 数据库设计简答题 数据库第九章 查询处理和优化简答题 数据库第十第十一章 恢复和并发简答题 2015期末 1、在数据库中,下列说…...
WeNet语音识别+Qwen-72B-Chat Bot+Sambert-Hifigan语音合成
WeNet语音识别Qwen-72B-Chat Bot👾Sambert-Hifigan语音合成 简介 利用 WeNet 进行语音识别,使用户能够通过语音输入与系统进行交互。接着,Qwen-72B-Chat Bot作为聊天机器人接收用户的语音输入或文本输入,提供响应并与用户进行对话…...
是否需要跟上鸿蒙(OpenHarmony)开发岗位热潮?
前言 自打华为2019年发布鸿蒙操作系统以来,网上各种声音百家争鸣。尤其是2023年发布会公布的鸿蒙4.0宣称不再支持Android,更激烈的讨论随之而来。 本文没有宏大的叙事,只有基于现实的考量。 通过本文,你将了解到: Har…...
【Golang】Json 无法表示 float64 类型的 NaN 以及 Inf 导致的 panic
【Golang】Json 无法表示 float64 类型的 NaN 以及 Inf 导致的 panic 原因 golang 服务出现了 panic,根据 panic 打印出的堆栈找到了问题代码,看上去原因是:json 序列化时,遇到了无法序列化的内容 [panic]: json: unsupported …...
bootstrap5实现宠物商店网站 Cat-Master
一、需求分析 宠物商店网站是指专门为宠物商店或宠物用品商家而建立的在线平台。这种网站的功能通常旨在提供以下服务: 产品展示:宠物商店网站通常会展示宠物食品、玩具、床上用品、健康护理产品等各种宠物用品的图片和详细信息。这样,潜在的…...
基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建并初始化TcpServer实例 以及 启动
对于一个TcpServer来说,它的灵魂是什么?就是需要提供一个事件循环EventLop(EventLoop),不停地去检测有没有客户端的连接到达,有没有客户端给服务器发送数据,描述的这些动作,反应堆模型能够胜任。当服务器和…...
边缘计算设备是什么意思。
问题描述:边缘计算设备是什么意思。 问题解答: 边缘计算(Edge Computing)是一种计算模型,其主要思想是在距离数据产生源头更近的地方进行数据处理和计算,而不是将所有数据传输到远程云服务器进行处理。边…...
使用ChatGPT midjourney 等AI智能工具,能为视觉营销做些什么?
使用ChatGPT、Midjourney等AI智能工具,可以极大地提升视觉营销的效率和创意水平。以下是这些工具在视觉营销中的一些具体应用: 内容创作与文案撰写(ChatGPT) 广告文案生成:根据产品特点和目标受众,生成吸…...
图像分割实战-系列教程4:unet医学细胞分割实战2(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)
🍁🍁🍁图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 unet医学细胞分割实战1 unet医学细胞分割实战2 unet医学细胞分割实战3 unet医学细胞分割实战4 unet…...
防火墙未开端口导致zookeeper集群异常,kafka起不来
转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 问题描述: 主机信息: IPhostname10.0.0.10host1010.0.0.12host1210.0.0.13host13 在这三台主机上部署…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
