下载
编译与部署
开始使用
操作手册
- 数据导入
- 表结构变更
- 物化视图
- HTTP API
- FE
- MANAGER
- Bootstrap Action
- Cancel Load Action
- Check Decommission Action
- Check Storage Type Action
- Config Action
- Connection Action
- Get DDL Statement Action
- Get Load Info Action
- Get Load State
- Get FE log file
- Get Small File
- HA Action
- Hardware Info Action
- Health Action
- Log Action
- Logout Action
- Meta Action
- Meta Action
- Meta Replay State Action
- Profile Action
- Query Detail Action
- Query Profile Action
- Row Count Action
- Session Action
- Set Config Action
- Show Data Action
- Show Meta Info Action
- Show Proc Action
- Show Runtime Info Action
- Statement Execution Action
- System Action
- Table Query Plan Action
- Table Row Count Action
- Table Schema Action
- Upload Action
- CANCEL LABEL
- Compaction Action
- CONNECTION
- getlogfile
- GET LABEL STATE
- GET TABLETS ON A PARTICULAR BE
- PROFILE
- QUERY DETAIL
- RESTORE TABLET
- SHOW DATA
- MIGRATE SINGLE TABLET TO A PARTICULAR DISK
- GET TABLETS DISTRIBUTION BETWEEN DIFFERENT DISKS
- FE
- 运维操作
- 配置文件
- 拦截规则
- 备份与恢复
- Broker
- Colocation Join
- Bucket Shuffle Join
- 动态分区
- 数据导出
- 导出查询结果集
- 分区缓存
- 权限管理
- LDAP
- 资源管理
- 查询执行的统计
- Runtime Filter
- Segment V2 升级手册
- 文件管理器
- SQL MODE
- 时区
- 变量
- 更新
- 多租户和资源划分
最佳实践
扩展功能
- 审计日志插件
- Doris On ES
- Doris output plugin
- ODBC External Table Of Doris
- Doris 插件框架
- Spark Doris Connector
- Flink Doris Connector
- DataX doriswriter
- UDF
设计文档
SQL 手册
- SQL 函数
- 日期函数
- convert_tz
- curdate
- current_timestamp
- curtime,current_time
- date_add
- date_format
- date_sub
- datediff
- day
- dayname
- dayofmonth
- dayofweek
- dayofyear
- from_days
- from_unixtime
- hour
- makedate
- minute
- month
- monthname
- now
- second
- strtodate
- time_round
- timediff
- timestampadd
- timestampdiff
- to_days
- unix_timestamp
- utc_timestamp
- week
- weekofyear
- year
- yearweek
- 地理位置函数
- 字符串函数
- 聚合函数
- bitmap 函数
- Hash函数
- Doris 窗口函数使用
- CAST
- DIGITAL_MASKING
- 日期函数
- 语法帮助
- 用户账户管理
- 集群管理
- ADMIN CANCEL REPAIR
- ADMIN CLEAN TRASH
- ADMIN CHECK TABLET
- ADMIN REPAIR
- ADMIN SET CONFIG
- ADMIN SET REPLICA STATUS
- ADMIN SHOW CONFIG
- ADMIN SHOW REPLICA DISTRIBUTION
- ADMIN SHOW REPLICA STATUS
- ADMIN SHOW DATA SKEW
- ALTER CLUSTER
- ALTER SYSTEM
- CANCEL DECOMMISSION
- CREATE CLUSTER
- CREATE FILE
- DROP CLUSTER
- DROP FILE
- ENTER
- INSTALL PLUGIN
- LINK DATABASE
- MIGRATE DATABASE
- SET LDAPADMINPASSWORD
- SHOW BACKENDS
- SHOW BROKER
- SHOW FILE
- SHOW FRONTENDS
- SHOW FULL COLUMNS
- SHOW INDEX
- SHOW MIGRATIONS
- SHOW PLUGINS
- SHOW TABLE STATUS
- SHOW TRASH
- UNINSTALL PLUGIN
- DDL
- ALTER DATABASE
- ALTER TABLE
- ALTER VIEW
- BACKUP
- CANCEL ALTER
- CANCEL BACKUP
- CANCEL RESTORE
- CREATE DATABASE
- CREATE ENCRYPTKEY
- CREATE INDEX
- CREATE MATERIALIZED VIEW
- CREATE REPOSITORY
- CREATE RESOURCE
- CREATE TABLE LIKE
- CREATE TABLE
- CREATE VIEW
- DROP DATABASE
- DROP ENCRYPTKEY
- DROP INDEX
- DROP MATERIALIZED VIEW
- DROP REPOSITORY
- DROP RESOURCE
- DROP TABLE
- DROP VIEW
- HLL
- RECOVER
- RESTORE
- SHOW ENCRYPTKEYS
- SHOW RESOURCES
- TRUNCATE TABLE
- CREATE FUNCTION
- DROP FUNCTION
- SHOW FUNCTIONS
- DML
- BROKER LOAD
- CANCEL LOAD
- DELETE
- EXPORT
- GROUP BY
- LOAD
- MINI LOAD
- MULTI LOAD
- PAUSE ROUTINE LOAD
- RESUME ROUTINE LOAD
- ROUTINE LOAD
- SHOW ALTER
- SHOW BACKUP
- SHOW CREATE FUNCTION
- SHOW CREATE ROUTINE LOAD
- SHOW DATA
- SHOW DATABASES
- SHOW DELETE
- SHOW DYNAMIC PARTITION TABLES
- SHOW EXPORT
- SHOW LOAD
- SHOW PARTITIONS
- SHOW PROPERTY
- SHOW REPOSITORIES
- SHOW RESTORE
- SHOW ROUTINE LOAD TASK
- SHOW ROUTINE LOAD
- SHOW SNAPSHOT
- SHOW TABLES
- SHOW TABLET
- SHOW TRANSACTION
- SPARK LOAD
- STOP ROUTINE LOAD
- STREAM LOAD
- ALTER ROUTINE LOAD
- INSERT
- UPDATE
- 数据类型
- 辅助命令
开发者手册
- 调试工具
- Doris BE存储层Benchmark工具
- 使用 Eclipse 搭建 FE 开发环境
- 使用 IntelliJ IDEA 搭建 FE 开发环境
- Apache Doris Be 开发调试
- Java 代码格式化
- C++ 代码格式化
Apache 社区
User Defined Function
UDF 主要适用于,用户需要的分析能力 Doris 并不具备的场景。用户可以自行根据自己的需求,实现自定义的函数,并且通过 UDF 框架注册到 Doris 中,来扩展 Doris 的能力,并解决用户分析需求。
UDF 能满足的分析需求分为两种:UDF 和 UDAF。本文中的 UDF 指的是二者的统称。
- UDF: 用户自定义函数,这种函数会对单行进行操作,并且输出单行结果。当用户在查询时使用 UDF ,每行数据最终都会出现在结果集中。典型的 UDF 比如字符串操作 concat() 等。
- UDAF: 用户自定义的聚合函数,这种函数对多行进行操作,并且输出单行结果。当用户在查询时使用 UDAF,分组后的每组数据最后会计算出一个值并展结果集中。典型的 UDAF 比如集合操作 sum() 等。一般来说 UDAF 都会结合 group by 一起使用。
这篇文档主要讲述了,如何编写自定义的 UDF 函数,以及如何在 Doris 中使用它。
如果用户使用 UDF 功能并扩展了 Doris 的函数分析,并且希望将自己实现的 UDF 函数贡献回 Doris 社区给其他用户使用,这时候请看文档 Contribute UDF 。
编写 UDF 函数
在使用UDF之前,用户需要先在 Doris 的 UDF 框架下,编写自己的UDF函数。在contrib/udf/src/udf_samples/udf_sample.h|cpp
文件中是一个简单的 UDF Demo。
编写一个 UDF 函数需要以下几个步骤。
编写函数
创建对应的头文件、CPP文件,在CPP文件中实现你需要的逻辑。CPP文件中的实现函数格式与UDF的对应关系。
用户可以把自己的 source code 统一放在一个文件夹下。这里以 udf_sample 为例,目录结构如下:
└── udf_samples
├── uda_sample.cpp
├── uda_sample.h
├── udf_sample.cpp
└── udf_sample.h
非可变参数
对于非可变参数的UDF,那么两者之间的对应关系很直接。 比如INT MyADD(INT, INT)
的UDF就会对应IntVal AddUdf(FunctionContext* context, const IntVal& arg1, const IntVal& arg2)
。
AddUdf
可以为任意的名字,只要创建UDF的时候指定即可。- 实现函数中的第一个参数永远是
FunctionContext*
。实现者可以通过这个结构体获得一些查询相关的内容,以及申请一些需要使用的内存。具体使用的接口可以参考udf/udf.h
中的定义。 - 实现函数中从第二个参数开始需要与UDF的参数一一对应,比如
IntVal
对应INT
类型。这部分的类型都要使用const
引用。 - 返回参数与UDF的参数的类型要相对应。
可变参数
对于可变参数,可以参见以下例子,UDFString md5sum(String, ...)
对应的 实现函数是StringVal md5sumUdf(FunctionContext* ctx, int num_args, const StringVal* args)
md5sumUdf
这个也是可以任意改变的,创建的时候指定即可。- 第一个参数与非可变参数函数一样,传入的是一个
FunctionContext*
。 - 可变参数部分由两部分组成,首先会传入一个整数,说明后面还有几个参数。后面传入的是一个可变参数部分的数组。
类型对应关系
UDF Type | Argument Type |
---|---|
TinyInt | TinyIntVal |
SmallInt | SmallIntVal |
Int | IntVal |
BigInt | BigIntVal |
LargeInt | LargeIntVal |
Float | FloatVal |
Double | DoubleVal |
Date | DateTimeVal |
Datetime | DateTimeVal |
Char | StringVal |
Varchar | StringVal |
Decimal | DecimalVal |
编译 UDF 函数
由于 UDF 实现中依赖了 Doris 的 UDF 框架 , 所以在编译 UDF 函数的时候首先要对 Doris 进行编译,也就是对 UDF 框架进行编译。
编译完成后会生成,UDF 框架的静态库文件。之后引入 UDF 框架依赖,并编译 UDF 即可。
编译Doris
在 Doris 根目录下执行 sh build.sh
就会在 output/udf/
生成 UDF 框架的静态库文件 headers|libs
├── output
│ └── udf
│ ├── include
│ │ ├── uda_test_harness.h
│ │ └── udf.h
│ └── lib
│ └── libDorisUdf.a
编写 UDF 编译文件
准备 thirdparty
thirdparty
文件夹主要用于存放用户 UDF 函数依赖的第三方库,包括头文件及静态库。其中必须包含依赖的 Doris UDF 框架中udf.h
和libDorisUdf.a
这两个文件。这里以
udf_sample
为例, 在 用户自己udf_samples
目录用于存放 source code。在同级目录下再创建一个thirdparty
文件夹用于存放静态库。目录结构如下:├── thirdparty │ │── include │ │ └── udf.h │ └── lib │ └── libDorisUdf.a └── udf_samples
udf.h
是 UDF 框架头文件。存放路径为doris/output/udf/include/udf.h
。 用户需要将 Doris 编译产出中的这个头文件拷贝到自己的thirdparty
的 include 文件夹下。libDorisUdf.a
是 UDF 框架的静态库。Doris 编译完成后该文件存放在doris/output/udf/lib/libDorisUdf.a
。用户需要将该文件拷贝到自己的thirdparty
的 lib 文件夹下。*注意:UDF 框架的静态库只有完成 Doris 编译后才会生成。
准备编译 UDF 的 CMakeFiles.txt
CMakeFiles.txt 用于声明 UDF 函数如何进行编译。存放在源码文件夹下,与用户代码平级。这里以
udf_samples
为例目录结构如下:├── thirdparty └── udf_samples ├── CMakeLists.txt ├── uda_sample.cpp ├── uda_sample.h ├── udf_sample.cpp └── udf_sample.h
- 需要显示声明引用
libDorisUdf.a
- 声明
udf.h
头文件位置
- 需要显示声明引用
以 udf_sample 为例
```
# Include udf
include_directories(thirdparty/include)
# Set all libraries
add_library(udf STATIC IMPORTED)
set_target_properties(udf PROPERTIES IMPORTED_LOCATION thirdparty/lib/libDorisUdf.a)
# where to put generated libraries
set(LIBRARY_OUTPUT_PATH "${BUILD_DIR}/src/udf_samples")
# where to put generated binaries
set(EXECUTABLE_OUTPUT_PATH "${BUILD_DIR}/src/udf_samples")
add_library(udfsample SHARED udf_sample.cpp)
target_link_libraries(udfsample
udf
-static-libstdc++
-static-libgcc
)
add_library(udasample SHARED uda_sample.cpp)
target_link_libraries(udasample
udf
-static-libstdc++
-static-libgcc
)
```
如果用户的 UDF 函数还依赖了其他的三方库,则需要声明 include,lib,并在 `add_library` 中增加依赖。
所有文件准备齐后完整的目录结构如下:
├── thirdparty
│ │── include
│ │ └── udf.h
│ └── lib
│ └── libDorisUdf.a
└── udf_samples
├── CMakeLists.txt
├── uda_sample.cpp
├── uda_sample.h
├── udf_sample.cpp
└── udf_sample.h
准备好上述文件就可以直接编译 UDF 了
执行编译
在 udf_samples 文件夹下创建一个 build 文件夹,用于存放编译产出。
在 build 文件夹下运行命令 cmake ../
生成Makefile,并执行 make 就会生成对应动态库。
├── thirdparty
├── udf_samples
└── build
编译结果
编译完成后的 UDF 动态链接库就生成成功了。在 build/src/
下,以 udf_samples 为例,目录结构如下:
├── thirdparty
├── udf_samples
└── build
└── src
└── udf_samples
├── libudasample.so
└── libudfsample.so
创建 UDF 函数
通过上述的步骤后,你可以得到 UDF 的动态库(也就是编译结果中的 .so
文件)。你需要将这个动态库放到一个能够通过 HTTP 协议访问到的位置。
然后登录 Doris 系统,在 mysql-client 中通过 CREATE FUNCTION
语法创建 UDF 函数。你需要拥有ADMIN权限才能够完成这个操作。这时 Doris 系统内部就会存在刚才创建好的 UDF。
CREATE [AGGREGATE] FUNCTION
name ([argtype][,...])
[RETURNS] rettype
PROPERTIES (["key"="value"][,...])
说明:
- PROPERTIES中
symbol
表示的是,执行入口函数的对应symbol,这个参数是必须设定。你可以通过nm
命令来获得对应的symbol,比如nm libudfsample.so | grep AddUdf
获得到的_ZN9doris_udf6AddUdfEPNS_15FunctionContextERKNS_6IntValES4_
就是对应的symbol。 - PROPERTIES中
object_file
表示的是从哪里能够下载到对应的动态库,这个参数是必须设定的。 - name: 一个function是要归属于某个DB的,name的形式为
dbName
.funcName
。当dbName
没有明确指定的时候,就是使用当前session所在的db作为dbName
。
具体使用可以参见 CREATE FUNCTION
获取更详细信息。
使用 UDF
用户使用 UDF 必须拥有对应数据库的 SELECT
权限。
UDF 的使用与普通的函数方式一致,唯一的区别在于,内置函数的作用域是全局的,而 UDF 的作用域是 DB内部。当链接 session 位于数据内部时,直接使用 UDF 名字会在当前DB内部查找对应的 UDF。否则用户需要显示的指定 UDF 的数据库名字,例如 dbName
.funcName
。
删除 UDF函数
当你不再需要 UDF 函数时,你可以通过下述命令来删除一个 UDF 函数, 可以参考 DROP FUNCTION
。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论