六月婷婷AV,国产偷窥猎奇福利二区,日韩三级片。,好吊色网站,日韩成人中文在线视频,国产亚洲午夜啪啪,亚洲欧美另类国产精品,国产成人av1,任你艹在线观看

如何在 TDengine 中編寫自定義函數?

TAOS Data

2022-10-11 / , ,

小 T 導讀:雖然 TDengine 已經提供了非常多的常用計算函數,但是在具體實踐中,企業(yè)的開發(fā)團隊往往會因為自己特殊的業(yè)務需求,需要特有的計算函數,這時候,支持自定義函數功能就特別重要了。本文將介紹 TDengine 3.0 支持的 UDF 機制。

在使用 TDengine 這款時序數據庫(Time Series Database, TSDB)的時候,我們經常會用到各種內置函數,通過在數據庫中完成很多計算,可以大大簡化數據庫應用層的開發(fā)工作。

TDengine 提供了大量的內置函數,可以分為幾個大類:

  • 單行函數:單行函數為查詢結果中的每一行返回一個結果行
    • 數學函數:如 ABS、SIN、COS、LOG、POW 等
    • 字符串函數:如 CHAR_LENGTH、CONCAT、LOWER、SUBSTR、UPPER 等
    • 轉換函數:如 CAST、TO_JSON、TO_UNIXTIMESTAMP 等
    • 時間和日期函數:NOW、TIMEDIFF、TIMEZONE、TODAY 等
  • 聚合函數:聚合函數為查詢結果集的每一個分組返回單個結果行
    • 如 AVG、COUNT、STDDEV、SUM 等
  • 選擇函數
  • 時序數據特有函數
  • 系統(tǒng)信息函數

雖然 TDengine 已經提供了這么多常用的計算函數,但是在具體實踐中,企業(yè)的開發(fā)團隊往往會因為自己特殊的業(yè)務需求,需要特有的計算函數,這時候,支持自定義函數功能就特別重要了。

本文將具體介紹如何在 TDengine 中定義并使用自定義函數。

利用 UDF(User Defined Function) 功能,TDengine 可以插入用戶編寫的處理代碼并在查詢中使用它們,這樣就能很方便地解決特殊應用場景中的使用需求。 UDF 通常以數據表中的一列數據做為輸入,同時支持以嵌套子查詢的結果作為輸入。

TDengine 支持通過 C/C++ 語言來定義 UDF。TDengine 3.0 優(yōu)化了相關機制,所以本文描述的特性適用于 3.0 及以上版本。

基本概念

用戶可以通過 UDF 實現兩類函數:標量函數和聚合函數。標量函數對每行數據輸出一個值,如求絕對值 abs,正弦函數 sin,字符串拼接函數 concat 等。聚合函數對多行數據進行輸出一個值,如求平均數 avg,最大值 max 等。

實現 UDF 時,需要實現規(guī)定的接口函數

  • 標量函數需要實現標量接口函數 scalarfn
  • 聚合函數需要實現聚合接口函數 aggfn_start、aggfn、aggfn_finish
  • 如果需要初始化,實現 udf_init;如果需要清理工作,實現 udf_destroy

接口函數的名稱是 UDF 名稱,或者是 UDF 名稱和特定后綴(_start, _finish, _init, _destroy)的連接。列表中的scalarfn、aggfn、udf需要替換成udf函數名。

標量接口函數

int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)

其中 scalarFn 是函數名的占位符。這個函數對數據塊進行標量計算,通過設置resultColumn結構體中的變量設置值。

參數的具體含義是:

  • inputDataBlock: 輸入的數據塊
  • resultColumn: 輸出列

聚合接口函數

int32_t aggfn_start(SUdfInterBuf *interBuf)

int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf)

int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)

其中 aggfn 是函數名的占位符。首先調用aggfn_start生成結果buffer,然后相關的數據會被分為多個行數據塊,對每個數據塊調用 aggfn 用數據塊更新中間結果,最后再調用 aggfn_finish 從中間結果產生最終結果,最終結果只能含 0 或 1 條結果數據。

參數的具體含義是:

  • interBuf:中間結果 buffer。
  • inputBlock:輸入的數據塊。
  • newInterBuf:新的中間結果buffer。
  • result:最終結果。

UDF 初始化和銷毀

int32_t udf_init()

int32_t udf_destroy()

其中 udf 是函數名的占位符。udf_init 完成初始化工作。 udf_destroy 完成清理工作。如果沒有初始化工作,無需定義udf_init函數。

如果沒有清理工作,無需定義udf_destroy函數。 篇幅所限,相關數據結構的定義可以參考 UDF 文檔。

編譯 UDF

用戶定義函數的 C 語言源代碼無法直接被 TDengine 系統(tǒng)所使用,而是需要先編譯為 動態(tài)鏈接庫,之后才能載入 TDengine 系統(tǒng)。

假設我們編寫了自定義函數,保存在 add_one.c 文件中,在 Linux 上可以這樣編譯:

gcc -g -O0 -fPIC -shared add_one.c -o add_one.so

創(chuàng)建 UDF

用戶可以通過 SQL 指令在系統(tǒng)中加載客戶端所在主機上的 UDF 函數庫。一旦創(chuàng)建成功,則當前 TDengine 集群的所有用戶都可以在 SQL 指令中使用這些函數。UDF 存儲在系統(tǒng)的 MNode 節(jié)點上,因此即使重啟 TDengine 系統(tǒng),已經創(chuàng)建的 UDF 也仍然可用。

在創(chuàng)建 UDF 時,需要區(qū)分標量函數和聚合函數。

  • 創(chuàng)建標量函數
CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type;

例如,如下語句可以把 libbitand.so 創(chuàng)建為系統(tǒng)中可用的 UDF:

CREATE FUNCTION bit_and AS "/home/taos/udf_example/libbitand.so" OUTPUTTYPE INT;
  • 創(chuàng)建聚合函數:
CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ];

例如,如下語句可以把 libl2norm.so 創(chuàng)建為系統(tǒng)中可用的 UDF:

CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8;

如果不再需要,可以通過 DROP 指令刪除所創(chuàng)建的 UDF。

DROP FUNCTION function_name;

使用 UDF

在 SQL 指令中,可以直接以在系統(tǒng)中創(chuàng)建 UDF 時賦予的函數名來調用用戶定義函數。例如:

SELECT X(c1,c2) FROM table/stable;

表示對名為 c1、c2 的數據列調用名為 X 的用戶定義函數。SQL 指令中用戶定義函數可以配合 WHERE 等查詢特性來使用。

歡迎下載試用 TDengine 3.0,并嘗試編寫一個自定義函數。

歡迎添加小T微信:tdengine,加入物聯網技術討論群,第一時間了解 TDengine 官方信息,與關注前沿技術的同學們共同探討新技術、新玩法。

TDengine Database