blob: a5b447156952a179e114540c7aa5be268458478a [file] [log] [blame]
<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="generator" content="VuePress 2.0.0-beta.61" />
<meta name="theme" content="VuePress Theme Hope" />
<link rel="alternate" hreflang="en-us" href="https://iotdb.apache.org/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html"><meta property="og:url" content="https://iotdb.apache.org/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html"><meta property="og:site_name" content="IoTDB Website"><meta property="og:description" content="用户自定义函数 UDF(User Defined Function)即用户自定义函数。IoTDB 提供多种内建函数来满足您的计算需求,同时您还可以通过创建自定义函数来满足更多的计算需求。 根据此文档,您将会很快学会 UDF 的编写、注册、使用等操作。 UDF 类型 IoTDB 支持两种类型的 UDF 函数,如下表所示。 UDF 分类 描述 ------..."><meta property="og:type" content="article"><meta property="og:locale" content="zh-CN"><meta property="og:locale:alternate" content="en-US"><script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","headline":"","image":[""],"dateModified":null,"author":[]}</script><link rel="icon" href="/favicon.ico"><meta name="Description" content="Apache IoTDB: Time Series Database for IoT"><meta name="Keywords" content="TSDB, time series, time series database, IoTDB, IoT database, IoT data management,时序数据库, 时间序列管理, IoTDB, 物联网数据库, 实时数据库, 物联网数据管理, 物联网数据"><meta name="baidu-site-verification" content="wfKETzB3OT"><meta name="google-site-verification" content="mZWAoRY0yj_HAr-s47zHCGHzx5Ju-RVm5wDbPnwQYFo"><title>IoTDB Website</title><meta name="description" content="用户自定义函数 UDF(User Defined Function)即用户自定义函数。IoTDB 提供多种内建函数来满足您的计算需求,同时您还可以通过创建自定义函数来满足更多的计算需求。 根据此文档,您将会很快学会 UDF 的编写、注册、使用等操作。 UDF 类型 IoTDB 支持两种类型的 UDF 函数,如下表所示。 UDF 分类 描述 ------...">
<style>
:root {
--bg-color: #fff;
}
html[data-theme="dark"] {
--bg-color: #1d1e1f;
}
html,
body {
background: var(--bg-color);
}
</style>
<script>
const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
const systemDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
document.documentElement.setAttribute("data-theme", "dark");
}
</script>
<link rel="preload" href="/assets/style-2f652485.css" as="style"><link rel="stylesheet" href="/assets/style-2f652485.css">
<link rel="modulepreload" href="/assets/app-cbe6e1e7.js"><link rel="modulepreload" href="/assets/framework-44b8a372.js"><link rel="modulepreload" href="/assets/User-Defined-Function.html-b8c49c3e.js"><link rel="modulepreload" href="/assets/User-Defined-Function.html-41836043.js">
</head>
<body>
<div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">跳至主要內容</a><!--]--><!--[--><div class="theme-container has-toc"><!--[--><header class="navbar hide-icon" id="navbar"><div class="navbar-start"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!--[--><!----><!--]--><a href="/zh/" class="brand"><img class="logo" src="/logo.png" alt="IoTDB Website"><!----><span class="site-name hide-in-pad">IoTDB Website</span></a><!--[--><!----><!--]--></div><div class="navbar-center"><!--[--><!----><!--]--><!--[--><!----><!--]--></div><div class="navbar-end"><!--[--><!----><!--]--><div id="docsearch-container"></div><nav class="nav-links"><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="文档"><span class="title"><!---->文档</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/zh/UserGuide/Master/QuickStart/QuickStart.html" class="nav-link" aria-label="latest"><!---->latest<!----></a></li><li class="dropdown-item"><a href="/zh/UserGuide/V1.2.x/QuickStart/QuickStart.html" class="nav-link" aria-label="v1.2.x"><!---->v1.2.x<!----></a></li><li class="dropdown-item"><a href="/zh/UserGuide/V1.1.x/QuickStart/QuickStart.html" class="nav-link" aria-label="v1.1.x"><!---->v1.1.x<!----></a></li><li class="dropdown-item"><a href="/zh/UserGuide/V1.0.x/QuickStart/QuickStart.html" class="nav-link" aria-label="v1.0.x"><!---->v1.0.x<!----></a></li><li class="dropdown-item"><a href="/zh/UserGuide/V0.13.x/QuickStart/QuickStart.html" class="nav-link" aria-label="v0.13.x"><!---->v0.13.x<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><a href="https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=177051872" rel="noopener noreferrer" target="_blank" aria-label="系统设计" class="nav-link"><!---->系统设计<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="nav-item hide-in-mobile"><a href="/zh/Download/" class="nav-link" aria-label="下载"><!---->下载<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="社区"><span class="title"><!---->社区</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/zh/Community/About.html" class="nav-link" aria-label="关于社区"><!---->关于社区<!----></a></li><li class="dropdown-item"><a href="https://cwiki.apache.org/confluence/display/iotdb" rel="noopener noreferrer" target="_blank" aria-label="Wiki" class="nav-link"><!---->Wiki<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="/zh/Community/Community-Project-Committers.html" class="nav-link" aria-label="开发人员"><!---->开发人员<!----></a></li><li class="dropdown-item"><a href="/zh/Community/Community-Powered-By.html" class="nav-link" aria-label="技术支持"><!---->技术支持<!----></a></li><li class="dropdown-item"><a href="/Community/Materials.html" class="nav-link" aria-label="活动与报告"><!---->活动与报告<!----></a></li><li class="dropdown-item"><a href="/zh/Community/Feedback.html" class="nav-link" aria-label="交流与反馈"><!---->交流与反馈<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="开发"><span class="title"><!---->开发</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/zh/Development/VoteRelease.html" class="nav-link" aria-label="如何投票"><!---->如何投票<!----></a></li><li class="dropdown-item"><a href="/zh/Development/HowToCommit.html" class="nav-link" aria-label="如何提交代码"><!---->如何提交代码<!----></a></li><li class="dropdown-item"><a href="/zh/Development/HowToJoin.html" class="nav-link" aria-label="成为Contributor"><!---->成为Contributor<!----></a></li><li class="dropdown-item"><a href="/zh/Development/Committer.html" class="nav-link" aria-label="成为Committer"><!---->成为Committer<!----></a></li><li class="dropdown-item"><a href="/zh/Development/ContributeGuide.html" class="nav-link" aria-label="项目开发指南"><!---->项目开发指南<!----></a></li><li class="dropdown-item"><a href="/zh/Development/HowtoContributeCode.html" class="nav-link" aria-label="技术贡献指南"><!---->技术贡献指南<!----></a></li><li class="dropdown-item"><a href="/zh/Development/format-changelist.html" class="nav-link" aria-label="TsFile的更改列表"><!---->TsFile的更改列表<!----></a></li><li class="dropdown-item"><a href="/zh/Development/rpc-changelist" class="nav-link" aria-label="RPC变更清单"><!---->RPC变更清单<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="ASF"><span class="title"><!---->ASF</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="https://www.apache.org/" rel="noopener noreferrer" target="_blank" aria-label="基金会" class="nav-link"><!---->基金会<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/licenses/" rel="noopener noreferrer" target="_blank" aria-label="许可证" class="nav-link"><!---->许可证<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/security/" rel="noopener noreferrer" target="_blank" aria-label="安全" class="nav-link"><!---->安全<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/foundation/sponsorship.html" rel="noopener noreferrer" target="_blank" aria-label="赞助" class="nav-link"><!---->赞助<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/foundation/thanks.html" rel="noopener noreferrer" target="_blank" aria-label="致谢" class="nav-link"><!---->致谢<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/events/current-event" rel="noopener noreferrer" target="_blank" aria-label="活动" class="nav-link"><!---->活动<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li></ul></button></div></div></nav><div class="nav-item"><div class="dropdown-wrapper i18n-dropdown"><button class="dropdown-title" type="button" aria-label="选择语言"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon i18n-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="i18n icon" style="width:1rem;height:1rem;vertical-align:middle;"><path d="M379.392 460.8 494.08 575.488l-42.496 102.4L307.2 532.48 138.24 701.44l-71.68-72.704L234.496 460.8l-45.056-45.056c-27.136-27.136-51.2-66.56-66.56-108.544h112.64c7.68 14.336 16.896 27.136 26.112 35.84l45.568 46.08 45.056-45.056C382.976 312.32 409.6 247.808 409.6 204.8H0V102.4h256V0h102.4v102.4h256v102.4H512c0 70.144-37.888 161.28-87.04 210.944L378.88 460.8zM576 870.4 512 1024H409.6l256-614.4H768l256 614.4H921.6l-64-153.6H576zM618.496 768h196.608L716.8 532.48 618.496 768z"></path></svg><!--]--><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html" class="nav-link" aria-label="English"><!---->English<!----></a></li><li class="dropdown-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html" class="router-link-active router-link-exact-active nav-link active" aria-label="简体中文"><!---->简体中文<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><div class="nav-item"><a class="repo-link" href="https://github.com/apache/iotdb" target="_blank" rel="noopener noreferrer" aria-label="GitHub"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="github icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></svg></a></div><!--[--><!----><!--]--><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow start"></span></div><aside class="sidebar" id="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><section class="sidebar-group"><p class="sidebar-heading"><!----><span class="title">IoTDB用户手册 (V1.1.x)</span><!----></p><ul class="sidebar-links"></ul></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">关于IoTDB</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">快速上手</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">数据模式与概念</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">语法约定</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">应用编程接口</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">元数据操作</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">数据写入(数据更新)</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">数据删除</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">数据查询</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">运算符和函数</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Overview.html" class="nav-link sidebar-link sidebar-page" aria-label="概述"><!---->概述<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" aria-label="用户自定义函数"><!---->用户自定义函数<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#用户自定义函数" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="用户自定义函数"><!---->用户自定义函数<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-类型" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="UDF 类型"><!---->UDF 类型<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-依赖" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="UDF 依赖"><!---->UDF 依赖<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udtf-user-defined-timeseries-generating-function" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="UDTF(User Defined Timeseries Generating Function)"><!---->UDTF(User Defined Timeseries Generating Function)<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#完整-maven-项目示例" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="完整 Maven 项目示例"><!---->完整 Maven 项目示例<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-注册" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="UDF 注册"><!---->UDF 注册<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-卸载" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="UDF 卸载"><!---->UDF 卸载<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-查询" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="UDF 查询"><!---->UDF 查询<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#查看所有注册的-udf" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="查看所有注册的 UDF"><!---->查看所有注册的 UDF<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#用户权限管理" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="用户权限管理"><!---->用户权限管理<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#配置项" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="配置项"><!---->配置项<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#贡献-udf" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="贡献 UDF"><!---->贡献 UDF<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#已知的-udf-库实现" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="已知的 UDF 库实现"><!---->已知的 UDF 库实现<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#q-a" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="Q&amp;A"><!---->Q&amp;A<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Aggregation.html" class="nav-link sidebar-link sidebar-page" aria-label="聚合函数"><!---->聚合函数<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Mathematical.html" class="nav-link sidebar-link sidebar-page" aria-label="算数运算符和函数"><!---->算数运算符和函数<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Comparison.html" class="nav-link sidebar-link sidebar-page" aria-label="比较运算符和函数"><!---->比较运算符和函数<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Logical.html" class="nav-link sidebar-link sidebar-page" aria-label="逻辑运算符"><!---->逻辑运算符<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/String.html" class="nav-link sidebar-link sidebar-page" aria-label="字符串处理"><!---->字符串处理<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Conversion.html" class="nav-link sidebar-link sidebar-page" aria-label="数据类型转换"><!---->数据类型转换<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Constant.html" class="nav-link sidebar-link sidebar-page" aria-label="常序列生成"><!---->常序列生成<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Selection.html" class="nav-link sidebar-link sidebar-page" aria-label="选择函数"><!---->选择函数<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Continuous-Interval.html" class="nav-link sidebar-link sidebar-page" aria-label="区间查询"><!---->区间查询<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Variation-Trend.html" class="nav-link sidebar-link sidebar-page" aria-label="趋势计算"><!---->趋势计算<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Sample.html" class="nav-link sidebar-link sidebar-page" aria-label="采样函数"><!---->采样函数<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Time-Series.html" class="nav-link sidebar-link sidebar-page" aria-label="时间序列处理"><!---->时间序列处理<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Lambda.html" class="nav-link sidebar-link sidebar-page" aria-label="Lambda 表达式"><!---->Lambda 表达式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Data-Profiling.html" class="nav-link sidebar-link sidebar-page" aria-label="数据画像"><!---->数据画像<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Anomaly-Detection.html" class="nav-link sidebar-link sidebar-page" aria-label="异常检测"><!---->异常检测<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Data-Matching.html" class="nav-link sidebar-link sidebar-page" aria-label="数据匹配"><!---->数据匹配<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Frequency-Domain.html" class="nav-link sidebar-link sidebar-page" aria-label="频域分析"><!---->频域分析<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Data-Quality.html" class="nav-link sidebar-link sidebar-page" aria-label="数据质量"><!---->数据质量<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Data-Repairing.html" class="nav-link sidebar-link sidebar-page" aria-label="数据修复"><!---->数据修复<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Series-Discovery.html" class="nav-link sidebar-link sidebar-page" aria-label="序列发现"><!---->序列发现<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Machine-Learning.html" class="nav-link sidebar-link sidebar-page" aria-label="机器学习"><!---->机器学习<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">触发器</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">监控告警</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">权限管理</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">运维工具</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">端云协同</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">系统集成</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">分布式</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">FAQ</span><span class="arrow end"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">参考</span><span class="arrow end"></span></button><!----></section></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!----></h1><div class="page-info"><!----><!----><!----><!----><span class="page-reading-time-info" aria-label="阅读时间"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 20 分钟</span><meta property="timeRequired" content="PT20M"></span><!----><!----></div><hr></div><div class="toc-place-holder"><aside id="toc"><!--[--><!----><!--]--><div class="toc-header">此页内容<button class="print-button" title="打印"><svg xmlns="http://www.w3.org/2000/svg" class="icon print-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="print icon"><path d="M819.2 364.8h-44.8V128c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v236.8h-44.8C145.067 364.8 96 413.867 96 473.6v192c0 59.733 49.067 108.8 108.8 108.8h44.8V896c0 17.067 14.933 32 32 32h460.8c17.067 0 32-14.933 32-32V774.4h44.8c59.733 0 108.8-49.067 108.8-108.8v-192c0-59.733-49.067-108.8-108.8-108.8zM313.6 160h396.8v204.8H313.6V160zm396.8 704H313.6V620.8h396.8V864zM864 665.6c0 25.6-19.2 44.8-44.8 44.8h-44.8V588.8c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v121.6h-44.8c-25.6 0-44.8-19.2-44.8-44.8v-192c0-25.6 19.2-44.8 44.8-44.8h614.4c25.6 0 44.8 19.2 44.8 44.8v192z"></path></svg></button></div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#用户自定义函数" class="router-link-active router-link-exact-active toc-link level2">用户自定义函数</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-类型" class="router-link-active router-link-exact-active toc-link level3">UDF 类型</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-依赖" class="router-link-active router-link-exact-active toc-link level3">UDF 依赖</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udtf-user-defined-timeseries-generating-function" class="router-link-active router-link-exact-active toc-link level3">UDTF(User Defined Timeseries Generating Function)</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#完整-maven-项目示例" class="router-link-active router-link-exact-active toc-link level3">完整 Maven 项目示例</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-注册" class="router-link-active router-link-exact-active toc-link level3">UDF 注册</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-卸载" class="router-link-active router-link-exact-active toc-link level3">UDF 卸载</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#udf-查询" class="router-link-active router-link-exact-active toc-link level3">UDF 查询</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#查看所有注册的-udf" class="router-link-active router-link-exact-active toc-link level3">查看所有注册的 UDF</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#用户权限管理" class="router-link-active router-link-exact-active toc-link level3">用户权限管理</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#配置项" class="router-link-active router-link-exact-active toc-link level3">配置项</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#贡献-udf" class="router-link-active router-link-exact-active toc-link level3">贡献 UDF</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#已知的-udf-库实现" class="router-link-active router-link-exact-active toc-link level3">已知的 UDF 库实现</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/UserGuide/V1.1.x/Operators-Functions/User-Defined-Function.html#q-a" class="router-link-active router-link-exact-active toc-link level3">Q&amp;A</a></li><!----><!--]--></ul><!--]--></ul></div><!--[--><!----><!--]--></aside></div><!----><div class="theme-hope-content"><!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
--><h2 id="用户自定义函数" tabindex="-1"><a class="header-anchor" href="#用户自定义函数" aria-hidden="true">#</a> 用户自定义函数</h2><p>UDF(User Defined Function)即用户自定义函数。IoTDB 提供多种内建函数来满足您的计算需求,同时您还可以通过创建自定义函数来满足更多的计算需求。</p><p>根据此文档,您将会很快学会 UDF 的编写、注册、使用等操作。</p><h3 id="udf-类型" tabindex="-1"><a class="header-anchor" href="#udf-类型" aria-hidden="true">#</a> UDF 类型</h3><p>IoTDB 支持两种类型的 UDF 函数,如下表所示。</p><table><thead><tr><th>UDF 分类</th><th>描述</th></tr></thead><tbody><tr><td>UDTF(User Defined Timeseries Generating Function)</td><td>自定义时间序列生成函数。该类函数允许接收多条时间序列,最终会输出一条时间序列,生成的时间序列可以有任意多数量的数据点。</td></tr><tr><td>UDAF(User Defined Aggregation Function)</td><td>正在开发,敬请期待。</td></tr></tbody></table><h3 id="udf-依赖" tabindex="-1"><a class="header-anchor" href="#udf-依赖" aria-hidden="true">#</a> UDF 依赖</h3><p>如果您使用 <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> ,可以从 <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven 库<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> 中搜索下面示例中的依赖。请注意选择和目标 IoTDB 服务器版本相同的依赖版本。</p><div class="language-xml line-numbers-mode" data-ext="xml"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.iotdb<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>udf-api<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>1.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>provided<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="udtf-user-defined-timeseries-generating-function" tabindex="-1"><a class="header-anchor" href="#udtf-user-defined-timeseries-generating-function" aria-hidden="true">#</a> UDTF(User Defined Timeseries Generating Function)</h3><p>编写一个 UDTF 需要继承<code>org.apache.iotdb.udf.api.UDTF</code>类,并至少实现<code>beforeStart</code>方法和一种<code>transform</code>方法。</p><p>下表是所有可供用户实现的接口说明。</p><table><thead><tr><th style="text-align:left;">接口定义</th><th style="text-align:left;">描述</th><th>是否必须</th></tr></thead><tbody><tr><td style="text-align:left;"><code>void validate(UDFParameterValidator validator) throws Exception</code></td><td style="text-align:left;">在初始化方法<code>beforeStart</code>调用前执行,用于检测<code>UDFParameters</code>中用户输入的参数是否合法。</td><td></td></tr><tr><td style="text-align:left;"><code>void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception</code></td><td style="text-align:left;">初始化方法,在 UDTF 处理输入数据前,调用用户自定义的初始化行为。用户每执行一次 UDTF 查询,框架就会构造一个新的 UDF 类实例,该方法在每个 UDF 类实例被初始化时调用一次。在每一个 UDF 类实例的生命周期内,该方法只会被调用一次。</td><td></td></tr><tr><td style="text-align:left;"><code>void transform(Row row, PointCollector collector) throws Exception</code></td><td style="text-align:left;">这个方法由框架调用。当您在<code>beforeStart</code>中选择以<code>RowByRowAccessStrategy</code>的策略消费原始数据时,这个数据处理方法就会被调用。输入参数以<code>Row</code>的形式传入,输出结果通过<code>PointCollector</code>输出。您需要在该方法内自行调用<code>collector</code>提供的数据收集方法,以决定最终的输出数据。</td><td>与下面的方法二选一</td></tr><tr><td style="text-align:left;"><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td><td style="text-align:left;">这个方法由框架调用。当您在<code>beforeStart</code>中选择以<code>SlidingSizeWindowAccessStrategy</code>或者<code>SlidingTimeWindowAccessStrategy</code>的策略消费原始数据时,这个数据处理方法就会被调用。输入参数以<code>RowWindow</code>的形式传入,输出结果通过<code>PointCollector</code>输出。您需要在该方法内自行调用<code>collector</code>提供的数据收集方法,以决定最终的输出数据。</td><td>与上面的方法二选一</td></tr><tr><td style="text-align:left;"><code>void terminate(PointCollector collector) throws Exception</code></td><td style="text-align:left;">这个方法由框架调用。该方法会在所有的<code>transform</code>调用执行完成后,在<code>beforeDestory</code>方法执行前被调用。在一个 UDF 查询过程中,该方法会且只会调用一次。您需要在该方法内自行调用<code>collector</code>提供的数据收集方法,以决定最终的输出数据。</td><td></td></tr><tr><td style="text-align:left;"><code>void beforeDestroy() </code></td><td style="text-align:left;">UDTF 的结束方法。此方法由框架调用,并且只会被调用一次,即在处理完最后一条记录之后被调用。</td><td></td></tr></tbody></table><p>在一个完整的 UDTF 实例生命周期中,各个方法的调用顺序如下:</p><ol><li><code>void validate(UDFParameterValidator validator) throws Exception</code></li><li><code>void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception</code></li><li><code>void transform(Row row, PointCollector collector) throws Exception</code>或者<code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></li><li><code>void terminate(PointCollector collector) throws Exception</code></li><li><code>void beforeDestroy() </code></li></ol><p>注意,框架每执行一次 UDTF 查询,都会构造一个全新的 UDF 类实例,查询结束时,对应的 UDF 类实例即被销毁,因此不同 UDTF 查询(即使是在同一个 SQL 语句中)UDF 类实例内部的数据都是隔离的。您可以放心地在 UDTF 中维护一些状态数据,无需考虑并发对 UDF 类实例内部状态数据的影响。</p><p>下面将详细介绍各个接口的使用方法。</p><ul><li>void validate(UDFParameterValidator validator) throws Exception</li></ul><p><code>validate</code>方法能够对用户输入的参数进行验证。</p><p>您可以在该方法中限制输入序列的数量和类型,检查用户输入的属性或者进行自定义逻辑的验证。</p><p><code>UDFParameterValidator</code>的使用方法请见 Javadoc。</p><ul><li>void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception</li></ul><p><code>beforeStart</code>方法有两个作用:</p><ol><li>帮助用户解析 SQL 语句中的 UDF 参数</li><li>配置 UDF 运行时必要的信息,即指定 UDF 访问原始数据时采取的策略和输出结果序列的类型</li><li>创建资源,比如建立外部链接,打开文件等。</li></ol><h5 id="udfparameters" tabindex="-1"><a class="header-anchor" href="#udfparameters" aria-hidden="true">#</a> UDFParameters</h5><p><code>UDFParameters</code>的作用是解析 SQL 语句中的 UDF 参数(SQL 中 UDF 函数名称后括号中的部分)。参数包括序列类型参数和字符串 key-value 对形式输入的属性参数。</p><p>例子:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> UDF<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> <span class="token string">&#39;key1&#39;</span><span class="token operator">=</span><span class="token string">&#39;iotdb&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;key2&#39;</span><span class="token operator">=</span><span class="token string">&#39;123.45&#39;</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>用法:</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token class-name">String</span> stringValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getString</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// iotdb</span>
<span class="token class-name">Float</span> floatValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getFloat</span><span class="token punctuation">(</span><span class="token string">&quot;key2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 123.45</span>
<span class="token class-name">Double</span> doubleValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getDouble</span><span class="token punctuation">(</span><span class="token string">&quot;key3&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// null</span>
<span class="token keyword">int</span> intValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getIntOrDefault</span><span class="token punctuation">(</span><span class="token string">&quot;key4&quot;</span><span class="token punctuation">,</span> <span class="token number">678</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 678</span>
<span class="token comment">// do something</span>
<span class="token comment">// configurations</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="udtfconfigurations" tabindex="-1"><a class="header-anchor" href="#udtfconfigurations" aria-hidden="true">#</a> UDTFConfigurations</h5><p>您必须使用 <code>UDTFConfigurations</code> 指定 UDF 访问原始数据时采取的策略和输出结果序列的类型。</p><p>用法:</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token comment">// parameters</span>
<span class="token comment">// ...</span>
<span class="token comment">// configurations</span>
configurations
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">Type</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>其中<code>setAccessStrategy</code>方法用于设定 UDF 访问原始数据时采取的策略,<code>setOutputDataType</code>用于设定输出结果序列的类型。</p><ul><li>setAccessStrategy</li></ul><p>注意,您在此处设定的原始数据访问策略决定了框架会调用哪一种<code>transform</code>方法 ,请实现与原始数据访问策略对应的<code>transform</code>方法。当然,您也可以根据<code>UDFParameters</code>解析出来的属性参数,动态决定设定哪一种策略,因此,实现两种<code>transform</code>方法也是被允许的。</p><p>下面是您可以设定的访问原始数据的策略:</p><table><thead><tr><th style="text-align:left;">接口定义</th><th style="text-align:left;">描述</th><th>调用的<code>transform</code>方法</th></tr></thead><tbody><tr><td style="text-align:left;"><code>RowByRowAccessStrategy</code></td><td style="text-align:left;">逐行地处理原始数据。框架会为每一行原始数据输入调用一次<code>transform</code>方法。当 UDF 只有一个输入序列时,一行输入就是该输入序列中的一个数据点。当 UDF 有多个输入序列时,一行输入序列对应的是这些输入序列按时间对齐后的结果(一行数据中,可能存在某一列为<code>null</code>值,但不会全部都是<code>null</code>)。</td><td><code>void transform(Row row, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>SlidingTimeWindowAccessStrategy</code></td><td style="text-align:left;">以滑动时间窗口的方式处理原始数据。框架会为每一个原始数据输入窗口调用一次<code>transform</code>方法。一个窗口可能存在多行数据,每一行数据对应的是输入序列按时间对齐后的结果(一行数据中,可能存在某一列为<code>null</code>值,但不会全部都是<code>null</code>)。</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>SlidingSizeWindowAccessStrategy</code></td><td style="text-align:left;">以固定行数的方式处理原始数据,即每个数据处理窗口都会包含固定行数的数据(最后一个窗口除外)。框架会为每一个原始数据输入窗口调用一次<code>transform</code>方法。一个窗口可能存在多行数据,每一行数据对应的是输入序列按时间对齐后的结果(一行数据中,可能存在某一列为<code>null</code>值,但不会全部都是<code>null</code>)。</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>SessionTimeWindowAccessStrategy</code></td><td style="text-align:left;">以会话窗口的方式处理原始数据,框架会为每一个原始数据输入窗口调用一次<code>transform</code>方法。一个窗口可能存在多行数据,每一行数据对应的是输入序列按时间对齐后的结果(一行数据中,可能存在某一列为<code>null</code>值,但不会全部都是<code>null</code>)。</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>StateWindowAccessStrategy</code></td><td style="text-align:left;">以状态窗口的方式处理原始数据,框架会为每一个原始数据输入窗口调用一次<code>transform</code>方法。一个窗口可能存在多行数据。目前仅支持对一个物理量也就是一列数据进行开窗。</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr></tbody></table><p><code>RowByRowAccessStrategy</code>的构造不需要任何参数。</p><p>如图是<code>SlidingTimeWindowAccessStrategy</code>的开窗示意图。 <img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://raw.githubusercontent.com/apache/iotdb-bin-resources/main/docs/UserGuide/Process-Data/UDF-User-Defined-Function/timeWindow.png"></p><p><code>SlidingTimeWindowAccessStrategy</code>有多种构造方法,您可以向构造方法提供 3 类参数:</p><ol><li>时间轴显示时间窗开始和结束时间</li><li>划分时间轴的时间间隔参数(必须为正数)</li><li>滑动步长(不要求大于等于时间间隔,但是必须为正数)</li></ol><p>时间轴显示时间窗开始和结束时间不是必须要提供的。当您不提供这类参数时,时间轴显示时间窗开始时间会被定义为整个查询结果集中最小的时间戳,时间轴显示时间窗结束时间会被定义为整个查询结果集中最大的时间戳。</p><p>滑动步长参数也不是必须的。当您不提供滑动步长参数时,滑动步长会被设定为划分时间轴的时间间隔。</p><p>3 类参数的关系可见下图。策略的构造方法详见 Javadoc。</p><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://alioss.timecho.com/docs/img/github/99787878-47b51480-2b5b-11eb-8ed3-84088c5c30f7.png"><p>注意,最后的一些时间窗口的实际时间间隔可能小于规定的时间间隔参数。另外,可能存在某些时间窗口内数据行数量为 0 的情况,这种情况框架也会为该窗口调用一次<code>transform</code>方法。</p><p>如图是<code>SlidingSizeWindowAccessStrategy</code>的开窗示意图。 <img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://raw.githubusercontent.com/apache/iotdb-bin-resources/main/docs/UserGuide/Process-Data/UDF-User-Defined-Function/countWindow.png"></p><p><code>SlidingSizeWindowAccessStrategy</code>有多种构造方法,您可以向构造方法提供 2 个参数:</p><ol><li>窗口大小,即一个数据处理窗口包含的数据行数。注意,最后一些窗口的数据行数可能少于规定的数据行数。</li><li>滑动步长,即下一窗口第一个数据行与当前窗口第一个数据行间的数据行数(不要求大于等于窗口大小,但是必须为正数)</li></ol><p>滑动步长参数不是必须的。当您不提供滑动步长参数时,滑动步长会被设定为窗口大小。</p><p>如图是<code>SessionTimeWindowAccessStrategy</code>的开窗示意图。<strong>时间间隔小于等于给定的最小时间间隔 sessionGap 则分为一组。</strong><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://raw.githubusercontent.com/apache/iotdb-bin-resources/main/docs/UserGuide/Process-Data/UDF-User-Defined-Function/sessionWindow.png"></p><p><code>SessionTimeWindowAccessStrategy</code>有多种构造方法,您可以向构造方法提供 2 类参数:</p><ol><li>时间轴显示时间窗开始和结束时间。</li><li>会话窗口之间的最小时间间隔。</li></ol><p>如图是<code>StateWindowAccessStrategy</code>的开窗示意图。<strong>对于数值型数据,状态差值小于等于给定的阈值 delta 则分为一组。</strong><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://raw.githubusercontent.com/apache/iotdb-bin-resources/main/docs/UserGuide/Process-Data/UDF-User-Defined-Function/stateWindow.png"></p><p><code>StateWindowAccessStrategy</code>有四种构造方法。</p><ol><li>针对数值型数据,可以提供时间轴显示时间窗开始和结束时间以及对于单个窗口内部允许变化的阈值delta。</li><li>针对文本数据以及布尔数据,可以提供时间轴显示时间窗开始和结束时间。对于这两种数据类型,单个窗口内的数据是相同的,不需要提供变化阈值。</li><li>针对数值型数据,可以只提供单个窗口内部允许变化的阈值delta,时间轴显示时间窗开始时间会被定义为整个查询结果集中最小的时间戳,时间轴显示时间窗结束时间会被定义为整个查询结果集中最大的时间戳。</li><li>针对文本数据以及布尔数据,可以不提供任何参数,开始与结束时间戳见3中解释。</li></ol><p>StateWindowAccessStrategy 目前只能接收一列输入。策略的构造方法详见 Javadoc。</p><ul><li>setOutputDataType</li></ul><p>注意,您在此处设定的输出结果序列的类型,决定了<code>transform</code>方法中<code>PointCollector</code>实际能够接收的数据类型。<code>setOutputDataType</code>中设定的输出类型和<code>PointCollector</code>实际能够接收的数据输出类型关系如下:</p><table><thead><tr><th style="text-align:left;"><code>setOutputDataType</code>中设定的输出类型</th><th style="text-align:left;"><code>PointCollector</code>实际能够接收的输出类型</th></tr></thead><tbody><tr><td style="text-align:left;"><code>INT32</code></td><td style="text-align:left;"><code>int</code></td></tr><tr><td style="text-align:left;"><code>INT64</code></td><td style="text-align:left;"><code>long</code></td></tr><tr><td style="text-align:left;"><code>FLOAT</code></td><td style="text-align:left;"><code>float</code></td></tr><tr><td style="text-align:left;"><code>DOUBLE</code></td><td style="text-align:left;"><code>double</code></td></tr><tr><td style="text-align:left;"><code>BOOLEAN</code></td><td style="text-align:left;"><code>boolean</code></td></tr><tr><td style="text-align:left;"><code>TEXT</code></td><td style="text-align:left;"><code>java.lang.String</code><code>org.apache.iotdb.udf.api.type.Binary</code></td></tr></tbody></table><p>UDTF 输出序列的类型是运行时决定的。您可以根据输入序列类型动态决定输出序列类型。</p><p>下面是一个简单的例子:</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token comment">// do something</span>
<span class="token comment">// ...</span>
configurations
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span><span class="token function">getDataType</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li>void transform(Row row, PointCollector collector) throws Exception</li></ul><p>当您在<code>beforeStart</code>方法中指定 UDF 读取原始数据的策略为 <code>RowByRowAccessStrategy</code>,您就需要实现该方法,在该方法中增加对原始数据处理的逻辑。</p><p>该方法每次处理原始数据的一行。原始数据由<code>Row</code>读入,由<code>PointCollector</code>输出。您可以选择在一次<code>transform</code>方法调用中输出任意数量的数据点。需要注意的是,输出数据点的类型必须与您在<code>beforeStart</code>方法中设置的一致,而输出数据点的时间戳必须是严格单调递增的。</p><p>下面是一个实现了<code>void transform(Row row, PointCollector collector) throws Exception</code>方法的完整 UDF 示例。它是一个加法器,接收两列时间序列输入,当这两个数据点都不为<code>null</code>时,输出这两个数据点的代数和。</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">UDTF</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">Row</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>collector<span class="token punctuation">.</span></span><span class="token class-name">PointCollector</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">UDTFConfigurations</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>parameter<span class="token punctuation">.</span></span><span class="token class-name">UDFParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>strategy<span class="token punctuation">.</span></span><span class="token class-name">RowByRowAccessStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>type<span class="token punctuation">.</span></span><span class="token class-name">Type</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Adder</span> <span class="token keyword">implements</span> <span class="token class-name">UDTF</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token punctuation">{</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">Type</span><span class="token punctuation">.</span><span class="token constant">INT64</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">Row</span> row<span class="token punctuation">,</span> <span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>row<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">||</span> row<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
collector<span class="token punctuation">.</span><span class="token function">putLong</span><span class="token punctuation">(</span>row<span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> row<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">+</span> row<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</li></ul><p>当您在<code>beforeStart</code>方法中指定 UDF 读取原始数据的策略为 <code>SlidingTimeWindowAccessStrategy</code>或者<code>SlidingSizeWindowAccessStrategy</code>时,您就需要实现该方法,在该方法中增加对原始数据处理的逻辑。</p><p>该方法每次处理固定行数或者固定时间间隔内的一批数据,我们称包含这一批数据的容器为窗口。原始数据由<code>RowWindow</code>读入,由<code>PointCollector</code>输出。<code>RowWindow</code>能够帮助您访问某一批次的<code>Row</code>,它提供了对这一批次的<code>Row</code>进行随机访问和迭代访问的接口。您可以选择在一次<code>transform</code>方法调用中输出任意数量的数据点,需要注意的是,输出数据点的类型必须与您在<code>beforeStart</code>方法中设置的一致,而输出数据点的时间戳必须是严格单调递增的。</p><p>下面是一个实现了<code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code>方法的完整 UDF 示例。它是一个计数器,接收任意列数的时间序列输入,作用是统计并输出指定时间范围内每一个时间窗口中的数据行数。</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">UDTF</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">RowWindow</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>collector<span class="token punctuation">.</span></span><span class="token class-name">PointCollector</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">UDTFConfigurations</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>parameter<span class="token punctuation">.</span></span><span class="token class-name">UDFParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>strategy<span class="token punctuation">.</span></span><span class="token class-name">SlidingTimeWindowAccessStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>type<span class="token punctuation">.</span></span><span class="token class-name">Type</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Counter</span> <span class="token keyword">implements</span> <span class="token class-name">UDTF</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token punctuation">{</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">Type</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">SlidingTimeWindowAccessStrategy</span><span class="token punctuation">(</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;time_interval&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;sliding_step&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;display_window_begin&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;display_window_end&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">RowWindow</span> rowWindow<span class="token punctuation">,</span> <span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>rowWindow<span class="token punctuation">.</span><span class="token function">windowSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
collector<span class="token punctuation">.</span><span class="token function">putInt</span><span class="token punctuation">(</span>rowWindow<span class="token punctuation">.</span><span class="token function">windowStartTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> rowWindow<span class="token punctuation">.</span><span class="token function">windowSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li>void terminate(PointCollector collector) throws Exception</li></ul><p>在一些场景下,UDF 需要遍历完所有的原始数据后才能得到最后的输出结果。<code>terminate</code>接口为这类 UDF 提供了支持。</p><p>该方法会在所有的<code>transform</code>调用执行完成后,在<code>beforeDestory</code>方法执行前被调用。您可以选择使用<code>transform</code>方法进行单纯的数据处理,最后使用<code>terminate</code>将处理结果输出。</p><p>结果需要由<code>PointCollector</code>输出。您可以选择在一次<code>terminate</code>方法调用中输出任意数量的数据点。需要注意的是,输出数据点的类型必须与您在<code>beforeStart</code>方法中设置的一致,而输出数据点的时间戳必须是严格单调递增的。</p><p>下面是一个实现了<code>void terminate(PointCollector collector) throws Exception</code>方法的完整 UDF 示例。它接收一个<code>INT32</code>类型的时间序列输入,作用是输出该序列的最大值点。</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">UDTF</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">Row</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>collector<span class="token punctuation">.</span></span><span class="token class-name">PointCollector</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">UDTFConfigurations</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>parameter<span class="token punctuation">.</span></span><span class="token class-name">UDFParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>strategy<span class="token punctuation">.</span></span><span class="token class-name">RowByRowAccessStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>type<span class="token punctuation">.</span></span><span class="token class-name">Type</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Max</span> <span class="token keyword">implements</span> <span class="token class-name">UDTF</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> time<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">int</span> value<span class="token punctuation">;</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token punctuation">{</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">TSDataType</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">Row</span> row<span class="token punctuation">,</span> <span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>row<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">int</span> candidateValue <span class="token operator">=</span> row<span class="token punctuation">.</span><span class="token function">getInt</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>time <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> value <span class="token operator">&lt;</span> candidateValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
time <span class="token operator">=</span> row<span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
value <span class="token operator">=</span> candidateValue<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">terminate</span><span class="token punctuation">(</span><span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>time <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
collector<span class="token punctuation">.</span><span class="token function">putInt</span><span class="token punctuation">(</span>time<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li>void beforeDestroy()</li></ul><p>UDTF 的结束方法,您可以在此方法中进行一些资源释放等的操作。</p><p>此方法由框架调用。对于一个 UDF 类实例而言,生命周期中会且只会被调用一次,即在处理完最后一条记录之后被调用。</p><h3 id="完整-maven-项目示例" tabindex="-1"><a class="header-anchor" href="#完整-maven-项目示例" aria-hidden="true">#</a> 完整 Maven 项目示例</h3><p>如果您使用 <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>,可以参考我们编写的示例项目<strong>udf-example</strong>。您可以在 <a href="https://github.com/apache/iotdb/tree/master/example/udf" target="_blank" rel="noopener noreferrer">这里<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> 找到它。</p><h3 id="udf-注册" tabindex="-1"><a class="header-anchor" href="#udf-注册" aria-hidden="true">#</a> UDF 注册</h3><p>注册一个 UDF 可以按如下流程进行:</p><ol><li>实现一个完整的 UDF 类,假定这个类的全类名为<code>org.apache.iotdb.udf.UDTFExample</code></li><li>将项目打成 JAR 包,如果您使用 Maven 管理项目,可以参考上述 Maven 项目示例的写法</li><li>进行注册前的准备工作,根据注册方式的不同需要做不同的准备,具体可参考以下例子</li><li>使用以下 SQL 语句注册 UDF</li></ol><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> <span class="token operator">&lt;</span>UDF<span class="token operator">-</span>NAME<span class="token operator">&gt;</span> <span class="token keyword">AS</span> <span class="token operator">&lt;</span>UDF<span class="token operator">-</span>CLASS<span class="token operator">-</span><span class="token keyword">FULL</span><span class="token operator">-</span>PATHNAME<span class="token operator">&gt;</span> <span class="token punctuation">(</span><span class="token keyword">USING</span> URI URI<span class="token operator">-</span>STRING<span class="token punctuation">)</span>?
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h4 id="示例-注册名为example的-udf-以下两种注册方式任选其一即可" tabindex="-1"><a class="header-anchor" href="#示例-注册名为example的-udf-以下两种注册方式任选其一即可" aria-hidden="true">#</a> 示例:注册名为<code>example</code>的 UDF,以下两种注册方式任选其一即可</h4><h5 id="不指定uri" tabindex="-1"><a class="header-anchor" href="#不指定uri" aria-hidden="true">#</a> 不指定URI</h5><p>准备工作:<br> 使用该种方式注册时,您需要提前将 JAR 包放置到目录 <code>iotdb-server-1.0.0-all-bin/ext/udf</code>(该目录可配置) 下。<br><strong>注意,如果您使用的是集群,那么需要将 JAR 包放置到所有 DataNode 的该目录下</strong></p><p>注册语句:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> example <span class="token keyword">AS</span> <span class="token string">&#39;org.apache.iotdb.udf.UDTFExample&#39;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h5 id="指定uri" tabindex="-1"><a class="header-anchor" href="#指定uri" aria-hidden="true">#</a> 指定URI</h5><p>准备工作:<br> 使用该种方式注册时,您需要提前将 JAR 包上传到 URI 服务器上并确保执行注册语句的 IoTDB 实例能够访问该 URI 服务器。<br><strong>注意,您无需手动放置 JAR 包,IoTDB 会下载 JAR 包并正确同步到整个集群</strong></p><p>注册语句:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> example <span class="token keyword">AS</span> <span class="token string">&#39;org.apache.iotdb.udf.UDTFExample&#39;</span> <span class="token keyword">USING</span> URI <span class="token string">&#39;http://jar/example.jar&#39;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h4 id="注意" tabindex="-1"><a class="header-anchor" href="#注意" aria-hidden="true">#</a> 注意</h4><p>由于 IoTDB 的 UDF 是通过反射技术动态装载的,因此您在装载过程中无需启停服务器。</p><p>UDF 函数名称是大小写不敏感的。</p><p>请不要给 UDF 函数注册一个内置函数的名字。使用内置函数的名字给 UDF 注册会失败。</p><p>不同的 JAR 包中最好不要有全类名相同但实现功能逻辑不一样的类。例如 UDF(UDAF/UDTF):<code>udf1</code><code>udf2</code>分别对应资源<code>udf1.jar</code><code>udf2.jar</code>。如果两个 JAR 包里都包含一个<code>org.apache.iotdb.udf.UDTFExample</code>类,当同一个 SQL 中同时使用到这两个 UDF 时,系统会随机加载其中一个类,导致 UDF 执行行为不一致。</p><h3 id="udf-卸载" tabindex="-1"><a class="header-anchor" href="#udf-卸载" aria-hidden="true">#</a> UDF 卸载</h3><p>卸载 UDF 的 SQL 语法如下:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">FUNCTION</span> <span class="token operator">&lt;</span>UDF<span class="token operator">-</span>NAME<span class="token operator">&gt;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>可以通过如下 SQL 语句卸载上面例子中的 UDF:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">FUNCTION</span> example
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h3 id="udf-查询" tabindex="-1"><a class="header-anchor" href="#udf-查询" aria-hidden="true">#</a> UDF 查询</h3><p>UDF 的使用方法与普通内建函数的类似。</p><h4 id="支持的基础-sql-语法" tabindex="-1"><a class="header-anchor" href="#支持的基础-sql-语法" aria-hidden="true">#</a> 支持的基础 SQL 语法</h4><ul><li><code>SLIMIT</code> / <code>SOFFSET</code></li><li><code>LIMIT</code> / <code>OFFSET</code></li><li>支持值过滤</li><li>支持时间过滤</li></ul><h4 id="带-查询" tabindex="-1"><a class="header-anchor" href="#带-查询" aria-hidden="true">#</a> 带 * 查询</h4><p>假定现在有时间序列 <code>root.sg.d1.s1</code><code>root.sg.d1.s2</code></p><ul><li><strong>执行<code>SELECT example(*) from root.sg.d1</code></strong></li></ul><p>那么结果集中将包括<code>example(root.sg.d1.s1)</code><code>example(root.sg.d1.s2)</code>的结果。</p><ul><li><strong>执行<code>SELECT example(s1, *) from root.sg.d1</code></strong></li></ul><p>那么结果集中将包括<code>example(root.sg.d1.s1, root.sg.d1.s1)</code><code>example(root.sg.d1.s1, root.sg.d1.s2)</code>的结果。</p><ul><li><strong>执行<code>SELECT example(*, *) from root.sg.d1</code></strong></li></ul><p>那么结果集中将包括<code>example(root.sg.d1.s1, root.sg.d1.s1)</code><code>example(root.sg.d1.s2, root.sg.d1.s1)</code><code>example(root.sg.d1.s1, root.sg.d1.s2)</code><code>example(root.sg.d1.s2, root.sg.d1.s2)</code>的结果。</p><h4 id="带自定义输入参数的查询" tabindex="-1"><a class="header-anchor" href="#带自定义输入参数的查询" aria-hidden="true">#</a> 带自定义输入参数的查询</h4><p>您可以在进行 UDF 查询的时候,向 UDF 传入任意数量的键值对参数。键值对中的键和值都需要被单引号或者双引号引起来。注意,键值对参数只能在所有时间序列后传入。下面是一组例子:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> <span class="token string">&#39;key1&#39;</span><span class="token operator">=</span><span class="token string">&#39;value1&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;key2&#39;</span><span class="token operator">=</span><span class="token string">&#39;value2&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> example<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">,</span> <span class="token string">&#39;key3&#39;</span><span class="token operator">=</span><span class="token string">&#39;value3&#39;</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> <span class="token string">&#39;key1&#39;</span><span class="token operator">=</span><span class="token string">&#39;value1&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;key2&#39;</span><span class="token operator">=</span><span class="token string">&#39;value2&#39;</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="与其他查询的嵌套查询" tabindex="-1"><a class="header-anchor" href="#与其他查询的嵌套查询" aria-hidden="true">#</a> 与其他查询的嵌套查询</h4><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> <span class="token operator">*</span><span class="token punctuation">,</span> example<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1 <span class="token keyword">DISABLE</span> ALIGN<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> s1 <span class="token operator">*</span> example<span class="token punctuation">(</span><span class="token operator">*</span> <span class="token operator">/</span> s1 <span class="token operator">+</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> s1 <span class="token operator">+</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span><span class="token punctuation">,</span> s1 <span class="token operator">-</span> example<span class="token punctuation">(</span>s1 <span class="token operator">+</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span> <span class="token operator">/</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="查看所有注册的-udf" tabindex="-1"><a class="header-anchor" href="#查看所有注册的-udf" aria-hidden="true">#</a> 查看所有注册的 UDF</h3><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SHOW</span> FUNCTIONS
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h3 id="用户权限管理" tabindex="-1"><a class="header-anchor" href="#用户权限管理" aria-hidden="true">#</a> 用户权限管理</h3><p>用户在使用 UDF 时会涉及到 3 种权限:</p><ul><li><code>CREATE_FUNCTION</code>:具备该权限的用户才被允许执行 UDF 注册操作</li><li><code>DROP_FUNCTION</code>:具备该权限的用户才被允许执行 UDF 卸载操作</li><li><code>READ_TIMESERIES</code>:具备该权限的用户才被允许使用 UDF 进行查询</li></ul><p>更多用户权限相关的内容,请参考 <a href="/zh/UserGuide/V1.1.x/Administration-Management/Administration.html" class="">权限管理语句</a></p><h3 id="配置项" tabindex="-1"><a class="header-anchor" href="#配置项" aria-hidden="true">#</a> 配置项</h3><p>使用配置项 <code>udf_lib_dir</code> 来配置 udf 的存储目录.<br> 在 SQL 语句中使用自定义函数时,可能提示内存不足。这种情况下,您可以通过更改配置文件<code>iotdb-datanode.properties</code>中的<code>udf_initial_byte_array_length_for_memory_control</code><code>udf_memory_budget_in_mb</code><code>udf_reader_transformer_collector_memory_proportion</code>并重启服务来解决此问题。</p><h3 id="贡献-udf" tabindex="-1"><a class="header-anchor" href="#贡献-udf" aria-hidden="true">#</a> 贡献 UDF</h3><!-- The template is copied and modified from the Apache Doris community--><p>该部分主要讲述了外部用户如何将自己编写的 UDF 贡献给 IoTDB 社区。</p><h4 id="前提条件" tabindex="-1"><a class="header-anchor" href="#前提条件" aria-hidden="true">#</a> 前提条件</h4><ol><li><p>UDF 具有通用性。</p><p>通用性主要指的是:UDF 在某些业务场景下,可以被广泛使用。换言之,就是 UDF 具有复用价值,可被社区内其他用户直接使用。</p><p>如果您不确定自己写的 UDF 是否具有通用性,可以发邮件到 <code>dev@iotdb.apache.org</code> 或直接创建 ISSUE 发起讨论。</p></li><li><p>UDF 已经完成测试,且能够正常运行在用户的生产环境中。</p></li></ol><h4 id="贡献清单" tabindex="-1"><a class="header-anchor" href="#贡献清单" aria-hidden="true">#</a> 贡献清单</h4><ol><li>UDF 的源代码</li><li>UDF 的测试用例</li><li>UDF 的使用说明</li></ol><h5 id="源代码" tabindex="-1"><a class="header-anchor" href="#源代码" aria-hidden="true">#</a> 源代码</h5><ol><li><code>node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin</code>中创建 UDF 主类和相关的辅助类。</li><li><code>node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java</code>中注册您编写的 UDF。</li></ol><h5 id="测试用例" tabindex="-1"><a class="header-anchor" href="#测试用例" aria-hidden="true">#</a> 测试用例</h5><p>您至少需要为您贡献的 UDF 编写集成测试。</p><p>您可以在<code>integration-test/src/test/java/org/apache/iotdb/db/it/udf</code>中为您贡献的 UDF 新增一个测试类进行测试。</p><h5 id="使用说明" tabindex="-1"><a class="header-anchor" href="#使用说明" aria-hidden="true">#</a> 使用说明</h5><p>使用说明需要包含:UDF 的名称、UDF 的作用、执行函数必须的属性参数、函数的适用的场景以及使用示例等。</p><p>使用说明需包含中英文两个版本。应分别在 <code>docs/zh/UserGuide/Operation Manual/DML Data Manipulation Language.md</code><code>docs/UserGuide/Operation Manual/DML Data Manipulation Language.md</code> 中新增使用说明。</p><h4 id="提交-pr" tabindex="-1"><a class="header-anchor" href="#提交-pr" aria-hidden="true">#</a> 提交 PR</h4><p>当您准备好源代码、测试用例和使用说明后,就可以将 UDF 贡献到 IoTDB 社区了。在 <a href="https://github.com/apache/iotdb" target="_blank" rel="noopener noreferrer">Github<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> 上面提交 Pull Request (PR) 即可。具体提交方式见:<a href="https://iotdb.apache.org/Development/HowToCommit.html" target="_blank" rel="noopener noreferrer">Pull Request Guide<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></p><p>当 PR 评审通过并被合并后,您的 UDF 就已经贡献给 IoTDB 社区了!</p><h3 id="已知的-udf-库实现" tabindex="-1"><a class="header-anchor" href="#已知的-udf-库实现" aria-hidden="true">#</a> 已知的 UDF 库实现</h3><ul><li><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Data-Profiling.html" class="">IoTDB-Quality</a>,一个关于数据质量的 UDF 库实现,包括数据画像、数据质量评估与修复等一系列函数。</li></ul><h3 id="q-a" tabindex="-1"><a class="header-anchor" href="#q-a" aria-hidden="true">#</a> Q&amp;A</h3><p>Q1: 如何修改已经注册的 UDF?</p><p>A1: 假设 UDF 的名称为<code>example</code>,全类名为<code>org.apache.iotdb.udf.UDTFExample</code>,由<code>example.jar</code>引入</p><ol><li>首先卸载已经注册的<code>example</code>函数,执行<code>DROP FUNCTION example</code></li><li>删除 <code>iotdb-server-1.0.0-all-bin/ext/udf</code> 目录下的<code>example.jar</code></li><li>修改<code>org.apache.iotdb.udf.UDTFExample</code>中的逻辑,重新打包,JAR 包的名字可以仍然为<code>example.jar</code></li><li>将新的 JAR 包上传至 <code>iotdb-server-1.0.0-all-bin/ext/udf</code> 目录下</li><li>装载新的 UDF,执行<code>CREATE FUNCTION example AS &quot;org.apache.iotdb.udf.UDTFExample&quot;</code></li></ol></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://github.com/apache/iotdb/edit/rel/1.1/docs/zh/UserGuide/Operators-Functions/User-Defined-Function.md" rel="noopener noreferrer" target="_blank" aria-label="发现错误?在 GitHub 上编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->发现错误?在 GitHub 上编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="meta-item git-info"><!----><!----></div></footer><nav class="page-nav"><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Overview.html" class="nav-link prev" aria-label="概述"><div class="hint"><span class="arrow start"></span>上一页</div><div class="link"><!---->概述</div></a><a href="/zh/UserGuide/V1.1.x/Operators-Functions/Aggregation.html" class="nav-link next" aria-label="聚合函数"><div class="hint">下一页<span class="arrow end"></span></div><div class="link">聚合函数<!----></div></a></nav><!----><!----><!--]--></main><!--]--><footer style="padding-bottom:2rem;"><span id="doc-version" style="display:none;">rel/1.1</span><p style="text-align:center;color:#909399;font-size:12px;margin:0 30px;">Copyright © 2023 The Apache Software Foundation.<br> Apache and the Apache feather logo are trademarks of The Apache Software Foundation</p><p style="text-align:center;margin-top:10px;color:#909399;font-size:12px;margin:0 30px;"><strong>Have a question?</strong> Connect with us on QQ, WeChat, or Slack. <a href="https://github.com/apache/iotdb/issues/1995">Join the community</a> now.</p><p style="text-align:center;margin-top:10px;color:#909399;font-size:12px;margin:0 30px;"> We use <a href="https://analytics.google.com">Google Analytics</a> to collect anonymous, aggregated usage information. </p></footer></div><!--]--><!--]--><!----><!--]--></div>
<script type="module" src="/assets/app-cbe6e1e7.js" defer></script>
</body>
</html>