From 7271e040d44851757c8b785926a44bd1aff306a5 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 8 Aug 2024 12:56:13 +0800 Subject: [PATCH 01/34] fix: restore delete_check.py case --- tests/parallel_test/cases.task | 2 +- tests/system-test/0-others/delete_check.py | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index e70042001d..2b0ddc8166 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -340,7 +340,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/splitVGroup.py -N 3 -n 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/splitVGroupWal.py -N 3 -n 3 ,,n,system-test,python3 ./test.py -f 0-others/timeRangeWise.py -N 3 -#,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/delete_check.py +,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/delete_check.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/test_hot_refresh_configurations.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/subscribe_stream_privilege.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/empty_identifier.py diff --git a/tests/system-test/0-others/delete_check.py b/tests/system-test/0-others/delete_check.py index ec589295e4..468ca63919 100644 --- a/tests/system-test/0-others/delete_check.py +++ b/tests/system-test/0-others/delete_check.py @@ -47,9 +47,9 @@ class TDTestCase: def compactDatbase(self): # compact database tdSql.execute(f"compact database {self.dbname}", show=True) - waitSeconds = 20 - if self.waitTranslation(waitSeconds) == False: - tdLog.exit(f"translation can not finish after wait {waitSeconds} seconds") + waitSeconds = 60 + if self.waitCompacts(waitSeconds) == False: + tdLog.exit(f"compacts can not finish after wait {waitSeconds} seconds") return # check tsdb folder empty @@ -108,6 +108,19 @@ class TDTestCase: return False + def waitCompacts(self, waitSeconds): + # wait end + for i in range(waitSeconds): + sql ="show compacts;" + rows = tdSql.query(sql) + if rows == 0: + return True + tdLog.info(f"i={i} wait for translation finish ...") + time.sleep(1) + + return False + + # run def run(self): # seed From c02ac1fe4c1a320519042193f2b865bbcfb0db0c Mon Sep 17 00:00:00 2001 From: xiao-77 Date: Thu, 8 Aug 2024 16:48:17 +0800 Subject: [PATCH 02/34] test: Adding test case for TD-31203 --- tests/parallel_test/cases.task | 1 + tests/system-test/2-query/agg_null.py | 162 ++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 tests/system-test/2-query/agg_null.py diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index e70042001d..d45627fcba 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -162,6 +162,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/stt_blocks_check.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/agg_null.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 2 diff --git a/tests/system-test/2-query/agg_null.py b/tests/system-test/2-query/agg_null.py new file mode 100644 index 0000000000..bb4fbf41a2 --- /dev/null +++ b/tests/system-test/2-query/agg_null.py @@ -0,0 +1,162 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import numpy as np +from util.log import * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * +from scipy.stats import gaussian_kde +from hyperloglog import HyperLogLog +''' +Test case for TS-5150 +''' +def approximate_percentile(data, percentile): + """ + 使用 KDE 近似计算百分位数。 + + Parameters: + - data: 包含数据的列表或数组 + - percentile: 要计算的百分位数(0到100之间) + + Returns: + - 近似百分位数的值 + """ + # 使用高斯核估计概率密度 + kde = gaussian_kde(data) + + # 生成一组足够密集的点,计算累积分布函数 + min_val = min(data) + max_val = max(data) + x = np.linspace(min_val, max_val, 1000) + cdf = np.cumsum(kde(x) / kde(x).sum()) + + # 找到最接近所需百分位数的值 + idx = np.abs(cdf - percentile / 100.0).argmin() + approximate_value = x[idx] + + return approximate_value +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.ts = 1537146000000 + def initdabase(self): + tdSql.execute('create database if not exists db_test vgroups 2 buffer 10') + tdSql.execute('use db_test') + tdSql.execute('create stable stb(ts timestamp, delay int) tags(groupid int)') + tdSql.execute('create table t1 using stb tags(1)') + tdSql.execute('create table t2 using stb tags(2)') + tdSql.execute('create table t3 using stb tags(3)') + tdSql.execute('create table t4 using stb tags(4)') + tdSql.execute('create table t5 using stb tags(5)') + tdSql.execute('create table t6 using stb tags(6)') + def insert_data(self): + for i in range(5000): + tdSql.execute(f"insert into t1 values({self.ts + i * 1000}, {i%5})") + tdSql.execute(f"insert into t2 values({self.ts + i * 1000}, {i%5})") + tdSql.execute(f"insert into t3 values({self.ts + i * 1000}, {i%5})") + + def verify_agg_null(self): + for i in range(20): + col_val_list = [] + tdSql.query(f'select CASE WHEN delay != 0 THEN delay ELSE NULL END from stb where ts between {1537146000000 + i * 1000} and {1537146000000 + (i+10) * 1000}') + for col_va in tdSql.queryResult: + if col_va[0] is not None: + col_val_list.append(col_va[0]) + tdSql.query(f'SELECT APERCENTILE(CASE WHEN delay != 0 THEN delay ELSE NULL END,50) AS apercentile,\ + MAX(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS maxDelay,\ + MIN(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS minDelay,\ + AVG(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS avgDelay,\ + STDDEV(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS jitter,\ + COUNT(CASE WHEN delay = 0 THEN 1 ELSE NULL END) AS timeoutCount,\ + COUNT(*) AS totalCount ,\ + ELAPSED(ts) AS elapsed_time,\ + SPREAD(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS spread,\ + SUM(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS sum,\ + HYPERLOGLOG(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS hyperloglog from stb where ts between {1537146000000 + i * 1000} and {1537146000000 + (i+10) * 1000}') + #verify apercentile + apercentile_res = tdSql.queryResult[0][0] + approximate_median = approximate_percentile(col_val_list, 50) + assert np.abs(apercentile_res - approximate_median) < 1 + #verify max + max_res = tdSql.queryResult[0][1] + tdSql.checkEqual(max_res,max(col_val_list)) + #verify min + min_res = tdSql.queryResult[0][2] + tdSql.checkEqual(min_res,min(col_val_list)) + #verify avg + avg_res = tdSql.queryResult[0][3] + tdSql.checkEqual(avg_res,np.average(col_val_list)) + #verify stddev + stddev_res = tdSql.queryResult[0][4] + assert np.abs(stddev_res - np.std(col_val_list)) < 0.0001 + #verify count of 0 + count of !0 == count(*) + count_res = tdSql.queryResult[0][6] + tdSql.checkEqual(count_res,len(col_val_list)+tdSql.queryResult[0][5]) + #verify elapsed + elapsed_res = tdSql.queryResult[0][7] + assert elapsed_res == 10000 + #verify spread + spread_res = tdSql.queryResult[0][8] + tdSql.checkEqual(spread_res,max(col_val_list) - min(col_val_list)) + #verify sum + sum_res = tdSql.queryResult[0][9] + tdSql.checkEqual(sum_res,sum(col_val_list)) + #verify hyperloglog + error_rate = 0.01 + hll = HyperLogLog(error_rate) + for col_val in col_val_list: + hll.add(col_val) + hll_res = tdSql.queryResult[0][10] + assert np.abs(hll_res - hll.card()) < 0.01 + #verify leastsquares + tdSql.query(f'SELECT leastsquares(CASE WHEN delay != 0 THEN delay ELSE NULL END,1,1) from stb where ts between {1537146000000 + i * 1000} and {1537146000000 + (i+10) * 1000}') + cleaned_data = tdSql.queryResult[0][0].strip('{}').replace(' ', '') + pairs = cleaned_data.split(',') + slope = None + intercept = None + for pair in pairs: + key, value = pair.split(':') + key = key.strip() + value = float(value.strip()) + if key == 'slop': + slope = value + elif key == 'intercept': + intercept = value + assert slope != 0 + assert intercept != 0 + #verify histogram + tdSql.query(f'SELECT histogram(CASE WHEN delay != 0 THEN delay ELSE NULL END, "user_input", "[1,3,5,7]", 1) from stb where ts between {1537146000000 + i * 1000} and {1537146000000 + (i+10) * 1000}') + cleaned_data = tdSql.queryResult[0][0].strip('{}').replace(' ', '') + pairs = cleaned_data.split(',') + count = None + for pair in pairs: + key, value = pair.split(':') + key = key.strip() + if key == 'count': + count = float(value.strip()) + assert count != 0 + def run(self): + self.initdabase() + self.insert_data() + self.verify_agg_null() + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) From ed710653eb0146809c8936a6418f2b077d687d75 Mon Sep 17 00:00:00 2001 From: dmchen Date: Thu, 8 Aug 2024 10:37:49 +0000 Subject: [PATCH 03/34] fix/TS-5262-log-conflict --- source/dnode/mnode/impl/src/mndTrans.c | 33 +++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c index 8ed3f66009..7f8d63c8e0 100644 --- a/source/dnode/mnode/impl/src/mndTrans.c +++ b/source/dnode/mnode/impl/src/mndTrans.c @@ -817,6 +817,17 @@ static bool mndCheckStbConflict(const char *conflict, STrans *pTrans) { return false; } +static void mndTransLogConflict(STrans *pNew, STrans *pTrans, bool conflict, bool *globalConflict) { + if (conflict) { + mError("trans:%d, db:%s stb:%s type:%d, can't execute since conflict with trans:%d db:%s stb:%s type:%d", pNew->id, + pNew->dbname, pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, pTrans->conflict); + *globalConflict = true; + } else { + mInfo("trans:%d, db:%s stb:%s type:%d, not conflict with trans:%d db:%s stb:%s type:%d", pNew->id, pNew->dbname, + pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, pTrans->conflict); + } +} + static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNew) { STrans *pTrans = NULL; void *pIter = NULL; @@ -832,18 +843,18 @@ static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNew) { if (pNew->conflict == TRN_CONFLICT_DB) { if (pTrans->conflict == TRN_CONFLICT_GLOBAL) conflict = true; if (pTrans->conflict == TRN_CONFLICT_DB || pTrans->conflict == TRN_CONFLICT_DB_INSIDE) { - if (mndCheckDbConflict(pNew->dbname, pTrans)) conflict = true; - if (mndCheckStbConflict(pNew->stbname, pTrans)) conflict = true; + mndTransLogConflict(pNew, pTrans, mndCheckDbConflict(pNew->dbname, pTrans), &conflict); + mndTransLogConflict(pNew, pTrans, mndCheckStbConflict(pNew->stbname, pTrans), &conflict); } } if (pNew->conflict == TRN_CONFLICT_DB_INSIDE) { if (pTrans->conflict == TRN_CONFLICT_GLOBAL) conflict = true; if (pTrans->conflict == TRN_CONFLICT_DB) { - if (mndCheckDbConflict(pNew->dbname, pTrans)) conflict = true; - if (mndCheckStbConflict(pNew->stbname, pTrans)) conflict = true; + mndTransLogConflict(pNew, pTrans, mndCheckDbConflict(pNew->dbname, pTrans), &conflict); + mndTransLogConflict(pNew, pTrans, mndCheckStbConflict(pNew->stbname, pTrans), &conflict); } if (pTrans->conflict == TRN_CONFLICT_DB_INSIDE) { - if (mndCheckStbConflict(pNew->stbname, pTrans)) conflict = true; // for stb + mndTransLogConflict(pNew, pTrans, mndCheckStbConflict(pNew->stbname, pTrans), &conflict); // for stb } } @@ -871,22 +882,16 @@ static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNew) { int32_t groupId = *(int32_t *)pGidIter; if (taosHashGet(pTrans->arbGroupIds, &groupId, sizeof(int32_t)) != NULL) { taosHashCancelIterate(pNew->arbGroupIds, pGidIter); - conflict = true; + mndTransLogConflict(pNew, pTrans, true, &conflict); break; + } else { + mndTransLogConflict(pNew, pTrans, false, &conflict); } pGidIter = taosHashIterate(pNew->arbGroupIds, pGidIter); } } } - if (conflict) { - mError("trans:%d, db:%s stb:%s type:%d, can't execute since conflict with trans:%d db:%s stb:%s type:%d", - pNew->id, pNew->dbname, pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, - pTrans->conflict); - } else { - mInfo("trans:%d, db:%s stb:%s type:%d, not conflict with trans:%d db:%s stb:%s type:%d", pNew->id, pNew->dbname, - pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, pTrans->conflict); - } sdbRelease(pMnode->pSdb, pTrans); } From 645b49023bfa092a2d1aac008a9db7d079205510 Mon Sep 17 00:00:00 2001 From: xiao-77 Date: Thu, 8 Aug 2024 19:39:43 +0800 Subject: [PATCH 04/34] add hyperloglog to requirements.txt --- tests/requirements.txt | 1 + tests/system-test/2-query/agg_null.py | 28 +-------------------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 5cdd9e02be..c6dd044c86 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -9,3 +9,4 @@ requests pexpect faker pyopenssl +hyperloglog \ No newline at end of file diff --git a/tests/system-test/2-query/agg_null.py b/tests/system-test/2-query/agg_null.py index bb4fbf41a2..bec879abbe 100644 --- a/tests/system-test/2-query/agg_null.py +++ b/tests/system-test/2-query/agg_null.py @@ -17,36 +17,10 @@ from util.cases import * from util.sql import * from util.common import * from util.sqlset import * -from scipy.stats import gaussian_kde from hyperloglog import HyperLogLog ''' Test case for TS-5150 ''' -def approximate_percentile(data, percentile): - """ - 使用 KDE 近似计算百分位数。 - - Parameters: - - data: 包含数据的列表或数组 - - percentile: 要计算的百分位数(0到100之间) - - Returns: - - 近似百分位数的值 - """ - # 使用高斯核估计概率密度 - kde = gaussian_kde(data) - - # 生成一组足够密集的点,计算累积分布函数 - min_val = min(data) - max_val = max(data) - x = np.linspace(min_val, max_val, 1000) - cdf = np.cumsum(kde(x) / kde(x).sum()) - - # 找到最接近所需百分位数的值 - idx = np.abs(cdf - percentile / 100.0).argmin() - approximate_value = x[idx] - - return approximate_value class TDTestCase: def init(self, conn, logSql, replicaVar=1): self.replicaVar = int(replicaVar) @@ -89,7 +63,7 @@ class TDTestCase: HYPERLOGLOG(CASE WHEN delay != 0 THEN delay ELSE NULL END) AS hyperloglog from stb where ts between {1537146000000 + i * 1000} and {1537146000000 + (i+10) * 1000}') #verify apercentile apercentile_res = tdSql.queryResult[0][0] - approximate_median = approximate_percentile(col_val_list, 50) + approximate_median = np.percentile(col_val_list, 50) assert np.abs(apercentile_res - approximate_median) < 1 #verify max max_res = tdSql.queryResult[0][1] From dd83d0f256a9167885cf6df139fd66855ccf7fde Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Fri, 9 Aug 2024 09:16:55 +0800 Subject: [PATCH 05/34] update tdinsight doc --- .../01-components/12-tdinsight/index.mdx | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx index 224fd5908d..2d4b69f46b 100644 --- a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx +++ b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx @@ -17,6 +17,12 @@ TDengine 通过 taosKeeper 将服务器的 CPU、内存、硬盘空间、带宽 - TDengine 已经安装并正常运行,此仪表盘需要 TDengine 3.0.0.0 及以上,并开启监控上报配置,具体配置请参考:[TDengine 监控配置](../taosd/#监控相关)。 - taosAdapter 已经安装并正常运行。具体细节请参考:[taosAdapter 参考手册](../taosadapter) - taosKeeper 已安装并正常运行。具体细节请参考:[taosKeeper 参考手册](../taoskeeper) +- Grafana 服务已安装并正常运行。我们建议您使用最新的 Grafana 版本,TDInsight 支持 Grafana 7.5 及以上版本。 + :::info + + 下文介绍中,都以 Grafana v11.0.0 版本为例,其他版本功能可能有差异,请参考 [Grafana 官网](https://grafana.com/docs/grafana/latest/)。 + + ::: 然后记录以下信息: @@ -24,22 +30,11 @@ TDengine 通过 taosKeeper 将服务器的 CPU、内存、硬盘空间、带宽 - taosAdapter 集群认证信息,可使用用户名及密码。 - taosKeeper 记录监控指标的数据库名称。 -## 安装和启动 Grafana -我们建议您使用最新的 Grafana 版本,TDInsight 支持 Grafana 7.5 及以上版本。您可以在任何[支持的操作系统](https://grafana.com/docs/grafana/latest/installation/requirements/#supported-operating-systems)中,按照 [Grafana 官方文档安装说明](https://grafana.com/docs/grafana/latest/installation/) 安装 Grafana。 -安装后请参考 [启动 Grafana](https://grafana.com/docs/grafana/latest/setup-grafana/start-restart-grafana/) 启动 Grafana 服务。 - -安装完成后就可以在 Web 浏览器中打开 Grafana 网址,默认是:`http://localhost:3000`。 默认用户名/密码都是 `admin`。Grafana 会要求在首次登录后更改密码。 - -:::info - -下文介绍中,都以 Grafana v11.0.0 版本为例,其他版本功能可能有差异,请参考 [Grafana 官网](https://grafana.com/docs/grafana/latest/)。 - -::: ## 安装 TDengine 数据源插件 -TDInsight 支持图形界面安装、手动安装和脚本安装三种安装方式,一般建议图形界面安装。对于 Grafana 8.5 以下版本可以使用手动安装和脚本安装方式。 +TDengine 数据源插件支持图形界面安装、手动安装和脚本安装三种安装方式,一般建议图形界面安装。对于 Grafana 8.5 以下版本可以使用手动安装和脚本安装方式。 From 3826fec13de2d5cc7107075e8f2fe1904e125cd1 Mon Sep 17 00:00:00 2001 From: 54liuyao <54liuyao> Date: Fri, 9 Aug 2024 09:28:13 +0800 Subject: [PATCH 06/34] adj error code --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 84ca2c36ea..880e73c5c0 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -4708,8 +4708,7 @@ int32_t tsdbReaderOpen2(void* pVnode, SQueryTableDataCond* pCond, void* pTableLi pReader->pSchemaMap = tSimpleHashInit(8, taosFastHash); if (pReader->pSchemaMap == NULL) { tsdbError("failed init schema hash for reader %s", pReader->idStr); - code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + TSDB_CHECK_NULL(pReader->pSchemaMap, code, lino, _err, terrno); } tSimpleHashSetFreeFp(pReader->pSchemaMap, freeSchemaFunc); From bc14da28e5277b1fc373ca5cc506c5e6d1468db9 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 9 Aug 2024 10:31:05 +0800 Subject: [PATCH 07/34] refactor: do some internal refactor. --- source/dnode/mnode/impl/src/mndStream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index dc8f494914..20f0e7b105 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -2420,7 +2420,7 @@ int32_t mndProcessStreamReqCheckpoint(SRpcMsg *pReq) { if (pStream != NULL) { // TODO:handle error code = mndProcessStreamCheckpointTrans(pMnode, pStream, checkpointId, 0, false); if (code) { - mError("failed to create checkpoint trans, code:%s", strerror(code)); + mError("failed to create checkpoint trans, code:%s", tstrerror(code)); } } else { // todo: wait for the create stream trans completed, and launch the checkpoint trans From 10acd19e714ece29a0d81e2250bf2195513259d4 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 9 Aug 2024 10:36:10 +0800 Subject: [PATCH 08/34] refactor: do some internal refactor. --- source/dnode/mnode/impl/src/mndMain.c | 2 +- source/libs/stream/src/streamSched.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dnode/mnode/impl/src/mndMain.c b/source/dnode/mnode/impl/src/mndMain.c index 37a171e9a4..11787a015b 100644 --- a/source/dnode/mnode/impl/src/mndMain.c +++ b/source/dnode/mnode/impl/src/mndMain.c @@ -443,7 +443,7 @@ static int32_t mndInitTimer(SMnode *pMnode) { (void)taosThreadAttrInit(&thAttr); (void)taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE); if ((code = taosThreadCreate(&pMnode->thread, &thAttr, mndThreadFp, pMnode)) != 0) { - mError("failed to create timer thread since %s", strerror(errno)); + mError("failed to create timer thread since %s", tstrerror(code)); TAOS_RETURN(code); } diff --git a/source/libs/stream/src/streamSched.c b/source/libs/stream/src/streamSched.c index 6506d449a6..e8c7be5204 100644 --- a/source/libs/stream/src/streamSched.c +++ b/source/libs/stream/src/streamSched.c @@ -107,7 +107,7 @@ void streamTaskResumeHelper(void* param, void* tmrId) { int32_t code = streamTaskSchedTask(pTask->pMsgCb, pTask->info.nodeId, pId->streamId, pId->taskId, STREAM_EXEC_T_RESUME_TASK); int32_t ref = atomic_sub_fetch_32(&pTask->status.timerActive, 1); if (code) { - stError("s-task:%s sched task failed, code:%s, ref:%d", pId->idStr, strerror(code), ref); + stError("s-task:%s sched task failed, code:%s, ref:%d", pId->idStr, tstrerror(code), ref); } else { stDebug("trigger to resume s-task:%s after being idled for %dms, ref:%d", pId->idStr, pTask->status.schedIdleTime, ref); From b170feeb226798d57d6b3ae42cca24d2d79efb52 Mon Sep 17 00:00:00 2001 From: t_max <1172915550@qq.com> Date: Fri, 9 Aug 2024 11:29:37 +0800 Subject: [PATCH 09/34] docs: update java demo and grafana alert --- .../com/taos/example/WSConnectExample.java | 4 +- docs/zh/08-develop/01-connect/index.md | 12 +- docs/zh/08-develop/02-sql.md | 2 +- docs/zh/08-develop/04-schemaless.md | 4 +- docs/zh/14-reference/05-connector/14-java.mdx | 2 +- docs/zh/14-reference/05-connector/index.md | 49 ++--- .../20-third-party/03-visual/01-grafana.mdx | 184 ++++++++++-------- .../java/com/taosdata/example/HikariDemo.java | 2 +- 8 files changed, 139 insertions(+), 120 deletions(-) diff --git a/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java b/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java index d683cc64a6..f920e77037 100644 --- a/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java +++ b/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java @@ -11,9 +11,9 @@ public class WSConnectExample { // ANCHOR: main public static void main(String[] args) throws SQLException { // use - // String jdbcUrl = "jdbc:TAOS-RS://localhost:6041/dbName?user=root&password=taosdata"; + // String jdbcUrl = "jdbc:TAOS-RS://localhost:6041/dbName?user=root&password=taosdata&batchfetch=true"; // if you want to connect a specified database named "dbName". - String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata"; + String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata&batchfetch=true"; Properties connProps = new Properties(); connProps.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT, "true"); diff --git a/docs/zh/08-develop/01-connect/index.md b/docs/zh/08-develop/01-connect/index.md index 2e0f284eeb..8e279e586e 100644 --- a/docs/zh/08-develop/01-connect/index.md +++ b/docs/zh/08-develop/01-connect/index.md @@ -259,17 +259,19 @@ dotnet add package TDengine.Connector ## 建立连接 在执行这一步之前,请确保有一个正在运行的,且可以访问到的 TDengine,而且服务端的 FQDN 配置正确。以下示例代码,都假设 TDengine 安装在本机,且 FQDN(默认 localhost) 和 serverPort(默认 6030) 都使用默认配置。 + ### 连接参数 连接的配置项较多,因此在建立连接之前,我们能先介绍一下各语言连接器建立连接使用的参数。 + Java 连接器建立连接的参数有 URL 和 Properties。 + TDengine 的 JDBC URL 规范格式为: + `jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}|&batchfetch={batchfetch}]` -Java 连接器建立连接的参数有 URL 和 Properties。 -TDengine 的 JDBC URL 规范格式为: -`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]` + URL 和 Properties 的详细参数说明和如何使用详见 [url 规范](../../reference/connector/java/#url-规范) -URL 和 Properties 的详细参数说明和如何使用详见 [url 规范](../../reference/connector/java/#url-规范) + **注**:REST 连接中增加 `batchfetch` 参数并设置为 true,将开启 WebSocket 连接。 @@ -343,7 +345,7 @@ DSN 的详细说明和如何使用详见 [连接功能](../../reference/connecto - **database**: 数据库名称。 - **params**: 其他参数。 例如token。 - - 完整 D 示例: + - 完整 DSN 示例: ```js ws://root:taosdata@localhost:6041 diff --git a/docs/zh/08-develop/02-sql.md b/docs/zh/08-develop/02-sql.md index 18d1072ce9..3bebe5e7a4 100644 --- a/docs/zh/08-develop/02-sql.md +++ b/docs/zh/08-develop/02-sql.md @@ -90,7 +90,7 @@ curl --location -uroot:taosdata 'http://127.0.0.1:6041/rest/sql/power' \ -> **注意**:如果不使用 `USE power` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 `power.meters`。 +> **注意**:建议采用 `.` 的格式构造SQL语句,不推荐在应用中采用 `USE DBName`方式访问。 ## 插入数据 下面以智能电表为例,展示如何使用连接器执行 SQL 来插入数据到 `power` 数据库的 `meters` 超级表。样例使用 TDengine 自动建表 SQL 语法,写入 d1001 子表中 3 条数据,写入 d1002 子表中 1 条数据,然后打印出实际插入数据条数。 diff --git a/docs/zh/08-develop/04-schemaless.md b/docs/zh/08-develop/04-schemaless.md index 2c5279f1d6..1bc750c3cb 100644 --- a/docs/zh/08-develop/04-schemaless.md +++ b/docs/zh/08-develop/04-schemaless.md @@ -169,7 +169,7 @@ st,t1=3,t2=4,t3=t3 c1=3i64,c6="passit" 1626006833640000000 ``` -执行带有 reqId 的无模式写入,此 reqId 可用于请求链路追踪。 +执行带有 reqId 的无模式写入,最后一个参数 reqId 可用于请求链路追踪。 ```java writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS, 1L); @@ -213,7 +213,7 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO {{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SchemalessJniTest.java:schemaless}} ``` -执行带有 reqId 的无模式写入,此 reqId 可用于请求链路追踪。 +执行带有 reqId 的无模式写入,最后一个参数 reqId 可用于请求链路追踪。 ```java writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS, 1L); diff --git a/docs/zh/14-reference/05-connector/14-java.mdx b/docs/zh/14-reference/05-connector/14-java.mdx index 8d19745668..0dc85feb13 100644 --- a/docs/zh/14-reference/05-connector/14-java.mdx +++ b/docs/zh/14-reference/05-connector/14-java.mdx @@ -199,7 +199,7 @@ Websocket 和 REST 连接使用驱动类 `com.taosdata.jdbc.rs.RestfulDriver`。 #### URL 规范 TDengine 的 JDBC URL 规范格式为: -`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]` +`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}|&batchfetch={batchfetch}]` 对于建立连接,原生连接与 REST 连接有细微不同。 Websocket 和 REST 连接使用驱动类 `com.taosdata.jdbc.rs.RestfulDriver`。原生连接使用驱动类 `com.taosdata.jdbc.TSDBDriver`。 diff --git a/docs/zh/14-reference/05-connector/index.md b/docs/zh/14-reference/05-connector/index.md index be25521a30..bc63bdff93 100644 --- a/docs/zh/14-reference/05-connector/index.md +++ b/docs/zh/14-reference/05-connector/index.md @@ -13,7 +13,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 目前 TDengine 的原生接口连接器可支持的平台包括:X64/ARM64 等硬件平台,以及 Linux/Win64 等开发环境。对照矩阵如下: | **CPU** | **OS** | **Java** | **Python** | **Go** | **Node.js** | **C#** | **Rust** | C/C++ | -| ------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ----- | +|---------------|-----------|----------|------------|--------|-------------|--------|----------|-------| | **X86 64bit** | **Linux** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **Win64** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **macOS** | ● | ● | ● | ○ | ○ | ● | ● | @@ -28,14 +28,14 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 TDengine 版本更新往往会增加新的功能特性,列表中的连接器版本为连接器最佳适配版本。 -| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -| ---------------------- | ------------- | ------------------------------------------- | ------------ | ------------- | --------------- | -------- | -| **3.3.0.0 及以上** | 3.3.2.0及以上 | taospy 2.7.15及以上,taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 | -| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 | -| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | -| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | +| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +|------------------------|----------|--------------------------------------|------------|---------------|-----------------|----------| +| **3.3.0.0 及以上** | 3.3.0及以上 | taospy 2.7.15及以上,taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 | +| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 | +| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | +| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | ## 功能特性 @@ -43,13 +43,13 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器 ### 使用原生接口(taosc) -| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -| ------------------- | -------- | ---------- | ------ | ------ | ----------- | -------- | -| **连接管理** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | +| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +|----------------|----------|------------|--------|--------|-------------|----------| +| **连接管理** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | +| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | +| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | +| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | :::info 由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。 @@ -57,17 +57,18 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器 ### 使用 http (REST 或 WebSocket) 接口 -| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -| ------------------------------ | -------- | ---------- | ------ | ------ | ----------- | -------- | -| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **批量拉取(基于 WebSocket)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +|------------------------|----------|------------|--------|--------|-------------|----------| +| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **批量拉取(基于 WebSocket)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | :::warning +- 参数绑定、数据订阅、Schemaless 和批量拉取功能仅在 WebSocket 连接下支持。 - 无论选用何种编程语言的连接器,2.0 及以上版本的 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池,以避免连接内的“USE statement”状态量在线程之间相互干扰(但连接的查询和写入操作都是线程安全的)。 ::: diff --git a/docs/zh/20-third-party/03-visual/01-grafana.mdx b/docs/zh/20-third-party/03-visual/01-grafana.mdx index 9d12e1db04..860087b901 100644 --- a/docs/zh/20-third-party/03-visual/01-grafana.mdx +++ b/docs/zh/20-third-party/03-visual/01-grafana.mdx @@ -22,8 +22,6 @@ TDengine 能够与开源数据可视化系统 [Grafana](https://www.grafana.com/ - TDengine 集群已经部署并正常运行。 - taosAdapter 已经安装并正常运行。具体细节请参考 [taosAdapter 的使用手册](../../../reference/components/taosadapter) - - 记录以下信息: - TDengine 集群 REST API 地址,如:`http://tdengine.local:6041`。 @@ -173,7 +171,6 @@ docker run -d \ - :::info 下文介绍中,都以 Grafana v11.0.0 版本为例,其他版本功能可能有差异,请参考 [Grafana 官网](https://grafana.com/docs/grafana/latest/)。 @@ -181,6 +178,7 @@ docker run -d \ ::: ## 内置变量和自定义变量 + Grafana 中的 Variable(变量)功能非常强大,可以在 Dashboard 的查询、面板标题、标签等地方使用,用来创建更加动态和交互式的 Dashbord,提高用户体验和效率。 变量的主要作用和特点包括: @@ -191,26 +189,30 @@ Grafana 中的 Variable(变量)功能非常强大,可以在 Dashboard 的 - 灵活的配置选项:变量提供了多种配置选项,如预定义的静态值列表、从数据源动态查询值、正则表达式过滤等,使得变量的应用更加灵活和强大。 - Grafana 提供了内置变量和自定义变量,它们都可以可以在编写 SQL 时引用,引用的方式是 `$variableName`,`variableName` 是变量的名字,其他引用方式请参考 [引用方式](https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/)。 ### 内置变量 + Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana 插件面板。其含义如下: - `from` 查询范围的起始时间 - `to` 查询范围的结束时间 - `interval` 窗口切分间隔 -对于每个查询都建议设置查询范围的起始时间和结束时间,可以有效的减少 TDengine 服务端执行查询扫描的数据量。`interval` 是窗口切分的大小,在 Grafana 11 版本中,其大小为时间间隔和返回点数计算而得。 +对于每个查询都建议设置查询范围的起始时间和结束时间,可以有效的减少 TDengine 服务端执行查询扫描的数据量。`interval` 是窗口切分的大小,在 Grafana 11 版本中,其大小为时间间隔和返回点数计算而得。 + 除了上述三个常用变量,Grafana 还提供了如 `__timezone`, `__org`, `__user` 等变量,详情请参考 [内置变量](https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables)。 ### 自定义变量 + 我们可以在 Dashbord 中增加自定义变量。自定义变量和内置变量的使用方式没有区别,都是在 SQL 中用 `$variableName` 进行引用。 自定义变量支持多种类型,常见的类型包括 `Query`(查询)、`Constant`(常量)、`Interval`(间隔)、`Data source`(数据源)等。 自定义变量可以引用其他自定义变量,比如一个变量表示区域,另一个变量可以引用区域的值,来查询这个区域的设备。 -#### 添加查询类型变量 + +#### 添加查询类型变量 + 在 Dashbord 的配置中,选择 【Variables】,然后点击 【New variable】: -1. 在 “Name“ 字段中,输入你的变量名,此处我们设置变量名为 `selected_groups`。 -2. 在 【Select variable type】下拉菜单中,选择 ”Query“(查询)。 +1. 在 “Name” 字段中,输入你的变量名,此处我们设置变量名为 `selected_groups`。 +2. 在 【Select variable type】下拉菜单中,选择 “Query”(查询)。 根据选择的变量类型,配置相应的选项。例如,如果选择了 “Query” 类型,你需要指定数据源和用于获取变量值的查询语句。此处我们还以智能电表为例,设置查询类型,选择数据源后,配置 SQL 为 `select distinct(groupid) from power.meters where groupid < 3 and ts > $from and ts < $to;` 3. 点击底部的【Run Query】后,可以在 “Preview of values”(值预览)部分,查看到根据你的配置生成的变量值。 4. 还有其他配置不再赘述,完成配置后,点击页面底部的【Apply】(应用)按钮,然后点击右上角的【Save dashboard】保存。 @@ -219,9 +221,10 @@ Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana 我们还可以再新增自定义变量来引用这个 `selected_groups` 变量,比如我们新增一个名为 `tbname_max_current` 的查询变量,其 SQL 为 `select tbname from power.meters where groupid = $selected_groups and ts > $from and ts < $to;` -#### 添加间隔类型变量 +#### 添加间隔类型变量 + 我们可以自定义时间窗口间隔,可以更加贴合业务需求。 -1. 在 “Name“ 字段中,输入变量名为 `interval`。 +1. 在 “Name” 字段中,输入变量名为 `interval`。 2. 在 【Select variable type】下拉菜单中,选择 “Interval”(间隔)。 3. 在 【Interval options】选项中输入 `1s,2s,5s,10s,15s,30s,1m`。 4. 还有其他配置不再赘述,完成配置后,点击页面底部的【Apply】(应用)按钮,然后点击右上角的【Save dashboard】保存。 @@ -235,6 +238,7 @@ Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana ::: ## TDengine 时间序列查询支持 + TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序业务场景需求的特色查询语法,这些语法能够为时序场景的应用的开发带来极大的便利。 - `partition by` 子句可以按一定的维度对数据进行切分,然后在切分出的数据空间内再进行一系列的计算。绝大多数情况可以替代 `group by`。 - `interval` 子句用于产生相等时间周期的窗口 @@ -249,13 +253,14 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 ![TDengine Database Grafana plugin create dashboard](./create_dashboard1.webp) -如上图所示,在 ”Query“ 中选中 `TDengine` 数据源,在下方查询框可输入相应 SQL 进行查询。 我们继续用智能电表来举例,为了展示曲线美观,此处**用了虚拟数据**。 +如上图所示,在 “Query” 中选中 `TDengine` 数据源,在下方查询框可输入相应 SQL 进行查询。 我们继续用智能电表来举例,为了展示曲线美观,此处**用了虚拟数据**。 ## 时间序列数据展示 + 假设我们想查询一段时间内的平均电流大小,时间窗口按 `$interval` 切分,若某一时间窗口区间数据缺失,填充 null。 -- “INPUT SQL“:输入要查询的语句(该 SQL 语句的结果集应为两列多行),此处输入:`select _wstart as ts, avg(current) as current from power.meters where groupid in ($selected_groups) and ts > $from and ts < $to interval($interval) fill(null)` ,其中,from、to 和 interval 为 Grafana 内置变量,selected_groups 为自定义变量。 -- “ALIAS BY“:可设置当前查询别名。 -- “GENERATE SQL“: 点击该按钮会自动替换相应变量,并生成最终执行的语句。 +- “INPUT SQL”:输入要查询的语句(该 SQL 语句的结果集应为两列多行),此处输入:`select _wstart as ts, avg(current) as current from power.meters where groupid in ($selected_groups) and ts > $from and ts < $to interval($interval) fill(null)` ,其中,from、to 和 interval 为 Grafana 内置变量,selected_groups 为自定义变量。 +- “ALIAS BY”:可设置当前查询别名。 +- “GENERATE SQL”: 点击该按钮会自动替换相应变量,并生成最终执行的语句。 在顶部的自定义变量中,若选择 `selected_groups` 的值为 1,则查询 `meters` 超级表中 `groupid` 为 1 的所有设备电流平均值变化如下图: @@ -268,10 +273,11 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 ::: ## 时间序列数据分组展示 + 假设我们想查询一段时间内的平均电流大小,按 `groupid` 分组展示,我们可以修改之前的 SQL 为 `select _wstart as ts, groupid, avg(current) as current from power.meters where ts > $from and ts < $to partition by groupid interval($interval) fill(null)` -- “Group by column(s)“: **半角**逗号分隔的 `group by` 或 `partition by` 列名。如果是 `group by` 或 `partition by` 查询语句,设置 “Group by“ 列,可以展示多维数据。此处设置 “Group by“ 列名为 `groupid`,可以按 `groupid` 分组展示数据。 -- “Group By Format“: `Group by` 或 `Partition by` 场景下多维数据 legend 格式化格式。例如上述 INPUT SQL,将 “Group By Format“ 设置为 `groupid-{{groupid}}`,展示的 legend 名字为格式化的分组名。 +- “Group by column(s)”: **半角**逗号分隔的 `group by` 或 `partition by` 列名。如果是 `group by` 或 `partition by` 查询语句,设置 “Group by” 列,可以展示多维数据。此处设置 “Group by” 列名为 `groupid`,可以按 `groupid` 分组展示数据。 +- “Group By Format”: `Group by` 或 `Partition by` 场景下多维数据 legend 格式化格式。例如上述 INPUT SQL,将 “Group By Format” 设置为 `groupid-{{groupid}}`,展示的 legend 名字为格式化的分组名。 完成设置后,按照 `groupid` 分组展示如下图: @@ -280,10 +286,10 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 > 关于如何使用 Grafana 创建相应的监测界面以及更多有关使用 Grafana 的信息,请参考 Grafana 官方的[文档](https://grafana.com/docs/)。 ## 性能建议 + - **所有查询加上时间范围**,在时序数据库中,如果不加查询的时间范围,会扫表导致性能低下。常见的 SQL 写法是 `select column_name from db.table where ts > $from and ts < $to;` - 对于最新状态类型的查询,我们一般建议在**创建数据库的时候打开缓存**(`CACHEMODEL` 设置为 last_row 或者 both),常见的 SQL 写法是 `select last(column_name) from db.table where ts > $from and ts < $to;` - ## 导入 Dashboard 在数据源配置页面,您可以为该数据源导入 TDinsight 面板,作为 TDengine 集群的监控可视化工具。如果 TDengine 服务端为 3.0 版本请选择 `TDinsight for 3.x` 导入。注意 TDinsight for 3.x 需要运行和配置 taoskeeper。 @@ -299,30 +305,36 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 - [15167](https://grafana.com/grafana/dashboards/15167): TDinsight - [16388](https://grafana.com/grafana/dashboards/16388): Telegraf 采集节点信息的数据展示 -## 告警配置简介 -### 告警配置流程 +## 告警配置 + TDengine Grafana 插件支持告警,如果要配置告警,需要以下几个步骤: -1. 配置联络点(“Contact points“):配置通知渠道,包括 DingDing、Email、Slack、WebHook、Prometheus Alertmanager 等 -2. 配置告警通知策略(“Notification policies“):配置告警发送到哪个通道的路由,以及发送通知的时间和重复频率 -3. 配置 “Alert rules“:配置详细的告警规则 +1. 配置联络点(“Contact points”):配置通知渠道,包括 DingDing、Email、Slack、WebHook、Prometheus Alertmanager 等 +2. 配置告警通知策略(“Notification policies”):配置告警发送到哪个通道的路由,以及发送通知的时间和重复频率 +3. 配置告警规则(“Alert rules”):配置详细的告警规则 3.1 配置告警名称 - 3.2 配置查询及告警触发条件 + 3.2 配置查询和告警触发条件 3.3 配置规则评估策略 3.4 配置标签和告警通道 3.5 配置通知文案 ### 告警配置界面 -在Grafana 11 告警界面一共有 6 个 Tab,分别是 “Alert rules“、“Contact points“、“Notification policies“、“Silences“、 “Groups“ 和 “Settings“。 -- “Alert rules“ 告警规则列表,用于展示和配置告警规则 -- “Contact points“ 通知渠道,包括 DingDing、Email、Slack、WebHook、Prometheus Alertmanager 等 -- “Notification policies“ 配置告警发送到哪个通道的路由,以及发送通知的时间和重复频率 -- “Silences“ 配置告警静默时间段 -- “Groups“ 告警组,配置的告警触发后会在这里分组显示 -- “Settings“ 提供通过 JSON 方式修改告警配置 -## 配置邮件联络点 -### Grafana Server 配置文件修改 -在 Grafana 服务的配置文件中添加 SMTP/Emailing 和 Alerting 模块,以 Linux 系统为例,其配置文件一般位于 `/etc/grafana/grafana.ini` +在Grafana 11 告警界面一共有 6 个 Tab,分别是 “Alert rules”、“Contact points”、“Notification policies”、“Silences”、 “Groups” 和 “Settings”。 +- “Alert rules” 告警规则列表,用于展示和配置告警规则 +- “Contact points” 通知渠道,包括 DingDing、Email、Slack、WebHook、Prometheus Alertmanager 等 +- “Notification policies” 配置告警发送到哪个通道的路由,以及发送通知的时间和重复频率 +- “Silences” 配置告警静默时间段 +- “Groups” 告警组,配置的告警触发后会在这里分组显示 +- “Settings” 提供通过 JSON 方式修改告警配置 + +### 配置联络点 + +以邮件和飞书为例配置联络点。 + +#### 配置邮件联络点 + +在 Grafana 服务的配置文件中添加 SMTP/Emailing 和 Alerting 模块。(以 Linux 系统为例,其配置文件一般位于 `/etc/grafana/grafana.ini`) + 在配置文件中增加下面内容: ```ini @@ -336,106 +348,110 @@ skip_verify = true from_address = sender@foxmail.com ``` -然后重启 Grafana 服务即可, 以 Linux 系统为例,执行 `systemctl restart grafana-server.service` +然后重启 Grafana 服务(以 Linux 系统为例,执行 `systemctl restart grafana-server.service`)即可添加完成 -### Grafana 页面创建新联络点 - -在 Grafana 页面找到 “Home“ -> “Alerting“ -> “Contact points“,创建新联络点 -”Name“: Email Contact Point -“Integration“:选择联络类型,这里选择 Email,填写邮件接收地址,完成后保存联络点 +在 Grafana 页面找到 “Home” -> “Alerting” -> “Contact points”,创建新联络点 +“Name”: Email Contact Point +“Integration”:选择联络类型,这里选择 Email,填写邮件接收地址,完成后保存联络点 ![TDengine Database Grafana plugin alert email](./alert-email.webp) -## 配置飞书联络点 +#### 配置飞书联络点 -### 飞书机器人配置 -1. “飞书工作台“ -> “获取应用“ -> “搜索飞书机器人助手“ -> “新建指令“ +按照以下步骤配置飞书机器人: + +1. “飞书工作台” -> “获取应用” -> “搜索飞书机器人助手” -> “新建指令” 2. 选择触发器:Grafana 3. 选择操作:通过官方机器人发送消息,填写发送对象和发送内容 ![TDengine Database Grafana plugin feishu robot](./alert-feishu1.webp) -### Grafana 配置飞书联络点 - -在 Grafana 页面找到 “Home“ -> “Alerting“ -> “Contact points“ 创建新联络点 -“Name“:Feishu Contact Point -“Integration“:选择联络类型,这里选择 Webhook,并填写 URL (在飞书机器人助手的 Grafana 触发器 Webhook 地址),完成后保存联络点 +在 Grafana 页面找到 “Home” -> “Alerting” -> “Contact points” 创建新联络点 +“Name”:Feishu Contact Point +“Integration”:选择联络类型,这里选择 Webhook,并填写 URL (在飞书机器人助手的 Grafana 触发器 Webhook 地址),完成后保存联络点 ![TDengine Database Grafana plugin feishu contact point](./alert-feishu2.webp) -## 通知策略 +### 配置告警通知策略 + 配置好联络点后,可以看到已有一个Default Policy ![TDengine Database Grafana plugin Notification default policy](./alert-notification1.webp) -点击右侧 ”...“ -> ”Edit“,然后编辑默认通知策略,弹出配置窗口: +点击右侧 “...” -> ”Edit”,然后编辑默认通知策略,弹出配置窗口: ![TDengine Database Grafana plugin Notification](./alert-notification2.webp) 然后配置下列参数: -- “Group wait“: 发送首次告警之前的等待时间。 -- “Group interval“: 发送第一个告警后,为该组发送下一批新告警的等待时间。 -- “Repeat interval“: 成功发送告警后再次重复发送告警的等待时间。 +- “Group wait”: 发送首次告警之前的等待时间。 +- “Group interval”: 发送第一个告警后,为该组发送下一批新告警的等待时间。 +- “Repeat interval”: 成功发送告警后再次重复发送告警的等待时间。 -## 配置告警规则 +### 配置告警规则 -### 配置查询和告警触发条件 +以配置智能电表告警为例,告警规则的配置主要包括告警名称、查询和告警触发条件、规则评估策略、标签和告警通道、通知文案。 -在需要配置告警的面板中选择 “Edit“ -> “Alert“ -> “New alert rule“。 +#### 配置告警名称 + +在需要配置告警的面板中选择 “Edit” -> “Alert” -> “New alert rule”。 + +“Enter alert rule name“ (输入告警规则名称):此处以智能电表为例输入 `power meters alert` + +#### 配置查询和告警触发条件 + +在 “Define query and alert condition” (定义查询和告警触发条件) 中配置告警规则。 +1. 选择数据源:`TDengine Datasource` +2. 查询语句: -1. “Enter alert rule name“ (输入告警规则名称):此处以智能电表为例输入 `power meters alert` -2. “Define query and alert condition“ (定义查询和告警触发条件) - 2.1 选择数据源:`TDengine Datasource` - 2.2 查询语句: ```sql select _wstart as ts, groupid, avg(current) as current from power.meters where ts > $from and ts < $to partition by groupid interval($interval) fill(null) ``` - 2.3 设置 ”Expression“(表达式):`Threshold is above 100` - 2.4 点击【Set as alert condition】 - 2.5 “Preview“:查看设置的规则的结果 + +3. 设置 “Expression”(表达式):`Threshold is above 100` +4. 点击【Set as alert condition】 +5. “Preview”:查看设置的规则的结果 完成设置后可以看到下面图片展示: ![TDengine Database Grafana plugin Alert Rules](./alert-rules1.webp) -### 配置表达式和计算规则 - -Grafana 的 “Expression“(表达式)支持对数据做各种操作和计算,其类型分为: -1. “Reduce“:将所选时间范围内的时间序列值聚合为单个值 - 1.1 “Function“ 用来设置聚合方法,支持 Min、Max、Last、Mean、Sum 和 Count。 - 1.2 “Mode“ 支持下面三种: - - “Strict“:如果查询不到数据,数据会赋值为 NaN。 - - “Drop Non-numeric Value“:去掉非法数据结果。 - - “Replace Non-numeric Value“:如果是非法数据,使用固定值进行替换。 -2. “Threshold“:检查时间序列数据是否符合阈值判断条件。当条件为假时返回 0,为真则返回1。支持下列方式: +Grafana 的 “Expression”(表达式)支持对数据做各种操作和计算,其类型分为: +1. “Reduce”:将所选时间范围内的时间序列值聚合为单个值 + 1.1 “Function” 用来设置聚合方法,支持 Min、Max、Last、Mean、Sum 和 Count。 + 1.2 “Mode” 支持下面三种: + - “Strict”:如果查询不到数据,数据会赋值为 NaN。 + - “Drop Non-numeric Value”:去掉非法数据结果。 + - “Replace Non-numeric Value”:如果是非法数据,使用固定值进行替换。 +2. “Threshold”:检查时间序列数据是否符合阈值判断条件。当条件为假时返回 0,为真则返回1。支持下列方式: - Is above (x > y) - Is below (x < y) - Is within range (x > y1 AND x < y2) - Is outside range (x < y1 AND x > y2) -3. “Math“:对时间序列的数据进行数学运算。 -4. “Resample“:更改每个时间序列中的时间戳使其具有一致的时间间隔,以便在它们之间执行数学运算。 -5. “Classic condition (legacy)“: 可配置多个逻辑条件,判断是否触发告警。 +3. “Math”:对时间序列的数据进行数学运算。 +4. “Resample”:更改每个时间序列中的时间戳使其具有一致的时间间隔,以便在它们之间执行数学运算。 +5. “Classic condition (legacy)”: 可配置多个逻辑条件,判断是否触发告警。 如上节截图显示,此处我们设置最大值超过 100 触发告警。 -### 配置评估策略 +#### 配置规则评估策略 ![TDengine Database Grafana plugin Alert Evaluation Behavior](./alert-evaluation.webp) 完成下面配置: -- “Folder“:设置告警规则所属目录。 -- “Evaluation group“:设置告警规则评估组。“Evaluation group“ 可以选择已有组或者新建组,新建组可以设置组名和评估时间间隔。 -- “Pending period“:在告警规则的阈值被触发后,异常值持续多长时间可以触发告警,合理设置可以避免误报。 +- “Folder”:设置告警规则所属目录。 +- “Evaluation group”:设置告警规则评估组。“Evaluation group” 可以选择已有组或者新建组,新建组可以设置组名和评估时间间隔。 +- “Pending period”:在告警规则的阈值被触发后,异常值持续多长时间可以触发告警,合理设置可以避免误报。 + +#### 配置标签和告警通道 -### 配置标签和告警通道 ![TDengine Database Grafana plugin Alert Labels and Notifications](./alert-labels.webp) 完成下面配置: -- “Labels“ 将标签添加到规则中,以便进行搜索、静默或路由到通知策略。 -- “Contact point“ 选择联络点,当告警发生时通过设置的联络点进行通知。 +- “Labels” 将标签添加到规则中,以便进行搜索、静默或路由到通知策略。 +- “Contact point” 选择联络点,当告警发生时通过设置的联络点进行通知。 -### 配置通知文案 +#### 配置通知文案 ![TDengine Database Grafana plugin Alert Labels and Notifications](./alert-annotations.webp) -设置 “Summary” 和 ”Description” 后,若告警触发,将会收到告警通知。 +设置 “Summary” 和 “Description” 后,若告警触发,将会收到告警通知。 diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/HikariDemo.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/HikariDemo.java index 79f636c428..4480cbc7c4 100644 --- a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/HikariDemo.java +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/HikariDemo.java @@ -21,7 +21,7 @@ public static void main(String[] args) throws SQLException { config.setConnectionTimeout(30000); //maximum wait milliseconds for get connection from pool config.setMaxLifetime(0); // maximum life time for each connection config.setIdleTimeout(0); // max idle time for recycle idle connection - config.setConnectionTestQuery("SELECT SERVER_STATUS()"); //validation query + config.setConnectionTestQuery("SELECT SERVER_VERSION()"); //validation query HikariDataSource ds = new HikariDataSource(config); //create datasource From 71b8f67ea681263212b5b4cd10ea687efafc2b3a Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 9 Aug 2024 11:37:34 +0800 Subject: [PATCH 10/34] refactor: do some internal refactor. --- source/dnode/mnode/impl/src/mndStreamUtil.c | 3 +++ source/dnode/vnode/src/tqCommon/tqCommon.c | 1 - source/libs/stream/src/streamDispatch.c | 8 ++++++-- source/libs/stream/src/streamHb.c | 10 +++++++--- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/source/dnode/mnode/impl/src/mndStreamUtil.c b/source/dnode/mnode/impl/src/mndStreamUtil.c index 47b0fdb412..383ffe16da 100644 --- a/source/dnode/mnode/impl/src/mndStreamUtil.c +++ b/source/dnode/mnode/impl/src/mndStreamUtil.c @@ -1069,6 +1069,9 @@ int32_t mndScanCheckpointReportInfo(SRpcMsg *pReq) { while ((pIter = taosHashIterate(execInfo.pChkptStreams, pIter)) != NULL) { SChkptReportInfo* px = (SChkptReportInfo *)pIter; + if (taosArrayGetSize(px->pTaskList) == 0) { + continue; + } STaskChkptInfo *pInfo = taosArrayGet(px->pTaskList, 0); if (pInfo == NULL) { diff --git a/source/dnode/vnode/src/tqCommon/tqCommon.c b/source/dnode/vnode/src/tqCommon/tqCommon.c index faca2020c5..7164c7f543 100644 --- a/source/dnode/vnode/src/tqCommon/tqCommon.c +++ b/source/dnode/vnode/src/tqCommon/tqCommon.c @@ -417,7 +417,6 @@ int32_t tqStreamTaskProcessDispatchRsp(SStreamMeta* pMeta, SRpcMsg* pMsg) { return code; } else { tqDebug("vgId:%d failed to handle the dispatch rsp, since find task:0x%x failed", vgId, pRsp->upstreamTaskId); - terrno = TSDB_CODE_STREAM_TASK_NOT_EXIST; return TSDB_CODE_STREAM_TASK_NOT_EXIST; } } diff --git a/source/libs/stream/src/streamDispatch.c b/source/libs/stream/src/streamDispatch.c index 493b5013d0..4da108507a 100644 --- a/source/libs/stream/src/streamDispatch.c +++ b/source/libs/stream/src/streamDispatch.c @@ -1083,7 +1083,7 @@ int32_t streamAddBlockIntoDispatchMsg(const SSDataBlock* pBlock, SStreamDispatch int32_t doSendDispatchMsg(SStreamTask* pTask, const SStreamDispatchReq* pReq, int32_t vgId, SEpSet* pEpSet) { void* buf = NULL; - int32_t code = -1; + int32_t code = 0; SRpcMsg msg = {0}; // serialize @@ -1093,9 +1093,9 @@ int32_t doSendDispatchMsg(SStreamTask* pTask, const SStreamDispatchReq* pReq, in goto FAIL; } - code = -1; buf = rpcMallocCont(sizeof(SMsgHead) + tlen); if (buf == NULL) { + code = terrno; goto FAIL; } @@ -1119,6 +1119,10 @@ FAIL: rpcFreeCont(buf); } + if (code == -1) { + code = TSDB_CODE_INVALID_MSG; + } + return code; } diff --git a/source/libs/stream/src/streamHb.c b/source/libs/stream/src/streamHb.c index 8513a8ba06..898e2bbc0b 100644 --- a/source/libs/stream/src/streamHb.c +++ b/source/libs/stream/src/streamHb.c @@ -295,10 +295,14 @@ void streamMetaHbToMnode(void* param, void* tmrId) { if (code) { stError("vgId:%d failed to send hmMsg to mnode, try again in 5s, code:%s", pMeta->vgId, tstrerror(code)); } - streamMetaRUnLock(pMeta); - streamTmrReset(streamMetaHbToMnode, META_HB_CHECK_INTERVAL, param, streamTimer, &pMeta->pHbInfo->hbTmr, pMeta->vgId, - "meta-hb-tmr"); + + if (code != TSDB_CODE_APP_IS_STOPPING) { + streamTmrReset(streamMetaHbToMnode, META_HB_CHECK_INTERVAL, param, streamTimer, &pMeta->pHbInfo->hbTmr, pMeta->vgId, + "meta-hb-tmr"); + } else { + stDebug("vgId:%d is stopping, not start hb again", pMeta->vgId); + } code = taosReleaseRef(streamMetaId, rid); if (code) { From a145d9db22518ace3680fa154d0a18ee9e7d74a6 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 9 Aug 2024 14:08:08 +0800 Subject: [PATCH 11/34] fix(stream): allowed continue hb msg. --- source/libs/stream/src/streamCheckpoint.c | 20 +++++++++++++------- source/libs/stream/src/streamHb.c | 10 +++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/source/libs/stream/src/streamCheckpoint.c b/source/libs/stream/src/streamCheckpoint.c index c555da9865..270f678d26 100644 --- a/source/libs/stream/src/streamCheckpoint.c +++ b/source/libs/stream/src/streamCheckpoint.c @@ -558,10 +558,17 @@ int32_t streamTaskUpdateTaskCheckpointInfo(SStreamTask* pTask, bool restored, SV id, vgId, pStatus.name, pInfo->checkpointId, pReq->checkpointId, pInfo->checkpointVer, pReq->checkpointVer, pInfo->checkpointTime, pReq->checkpointTs); } else { // not in restore status, must be in checkpoint status - stDebug("s-task:%s vgId:%d status:%s start to update the checkpoint-info, checkpointId:%" PRId64 "->%" PRId64 - " checkpointVer:%" PRId64 "->%" PRId64 " checkpointTs:%" PRId64 "->%" PRId64, - id, vgId, pStatus.name, pInfo->checkpointId, pReq->checkpointId, pInfo->checkpointVer, pReq->checkpointVer, - pInfo->checkpointTime, pReq->checkpointTs); + if (pStatus.state == TASK_STATUS__CK) { + stDebug("s-task:%s vgId:%d status:%s start to update the checkpoint-info, checkpointId:%" PRId64 "->%" PRId64 + " checkpointVer:%" PRId64 "->%" PRId64 " checkpointTs:%" PRId64 "->%" PRId64, + id, vgId, pStatus.name, pInfo->checkpointId, pReq->checkpointId, pInfo->checkpointVer, + pReq->checkpointVer, pInfo->checkpointTime, pReq->checkpointTs); + } else { + stDebug("s-task:%s vgId:%d status:%s NOT update the checkpoint-info, checkpointId:%" PRId64 "->%" PRId64 + " checkpointVer:%" PRId64 "->%" PRId64, + id, vgId, pStatus.name, pInfo->checkpointId, pReq->checkpointId, pInfo->checkpointVer, + pReq->checkpointVer); + } } ASSERT(pInfo->checkpointId <= pReq->checkpointId && pInfo->checkpointVer <= pReq->checkpointVer && @@ -573,12 +580,11 @@ int32_t streamTaskUpdateTaskCheckpointInfo(SStreamTask* pTask, bool restored, SV pInfo->checkpointVer = pReq->checkpointVer; pInfo->checkpointTime = pReq->checkpointTs; - streamTaskClearCheckInfo(pTask, true); code = streamTaskHandleEvent(pTask->status.pSM, TASK_EVENT_CHECKPOINT_DONE); - } else { - stDebug("s-task:0x%x vgId:%d not handle checkpoint-done event, status:%s", pReq->taskId, vgId, pStatus.name); } + streamTaskClearCheckInfo(pTask, true); + if (pReq->dropRelHTask) { stDebug("s-task:0x%x vgId:%d drop the related fill-history task:0x%" PRIx64 " after update checkpoint", pReq->taskId, vgId, pReq->hTaskId); diff --git a/source/libs/stream/src/streamHb.c b/source/libs/stream/src/streamHb.c index 898e2bbc0b..d2c5cb05b7 100644 --- a/source/libs/stream/src/streamHb.c +++ b/source/libs/stream/src/streamHb.c @@ -297,14 +297,10 @@ void streamMetaHbToMnode(void* param, void* tmrId) { } streamMetaRUnLock(pMeta); - if (code != TSDB_CODE_APP_IS_STOPPING) { - streamTmrReset(streamMetaHbToMnode, META_HB_CHECK_INTERVAL, param, streamTimer, &pMeta->pHbInfo->hbTmr, pMeta->vgId, - "meta-hb-tmr"); - } else { - stDebug("vgId:%d is stopping, not start hb again", pMeta->vgId); - } - + streamTmrReset(streamMetaHbToMnode, META_HB_CHECK_INTERVAL, param, streamTimer, &pMeta->pHbInfo->hbTmr, pMeta->vgId, + "meta-hb-tmr"); code = taosReleaseRef(streamMetaId, rid); + if (code) { stError("vgId:%d in meta timer, failed to release the meta rid:%" PRId64, pMeta->vgId, rid); } From 75e9c027a66b3304b58269b32724db794e2a4653 Mon Sep 17 00:00:00 2001 From: 54liuyao <54liuyao> Date: Fri, 9 Aug 2024 14:40:34 +0800 Subject: [PATCH 12/34] adj error code --- source/util/src/tscalablebf.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/source/util/src/tscalablebf.c b/source/util/src/tscalablebf.c index 72a97fee45..80b633f5e8 100644 --- a/source/util/src/tscalablebf.c +++ b/source/util/src/tscalablebf.c @@ -33,7 +33,7 @@ int32_t tScalableBfInit(uint64_t expectedEntries, double errorRate, SScalableBf* int32_t lino = 0; const uint32_t defaultSize = 8; if (expectedEntries < 1 || errorRate <= 0 || errorRate >= 1.0) { - code = TSDB_CODE_FAILED; + code = TSDB_CODE_INVALID_PARA; QUERY_CHECK_CODE(code, lino, _error); } SScalableBf* pSBf = taosMemoryCalloc(1, sizeof(SScalableBf)); @@ -71,7 +71,7 @@ int32_t tScalableBfPutNoCheck(SScalableBf* pSBf, const void* keyBuf, uint32_t le int32_t code = TSDB_CODE_SUCCESS; int32_t lino = 0; if (pSBf->status == SBF_INVALID) { - code = TSDB_CODE_FAILED; + code = TSDB_CODE_OUT_OF_BUFFER; QUERY_CHECK_CODE(code, lino, _error); } int32_t size = taosArrayGetSize(pSBf->bfArray); @@ -92,7 +92,7 @@ int32_t tScalableBfPutNoCheck(SScalableBf* pSBf, const void* keyBuf, uint32_t le _error: if (code != TSDB_CODE_SUCCESS) { - uError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); + uDebug("%s failed at line %d since %s", __func__, lino, tstrerror(code)); } return code; } @@ -101,7 +101,7 @@ int32_t tScalableBfPut(SScalableBf* pSBf, const void* keyBuf, uint32_t len, int3 int32_t code = TSDB_CODE_SUCCESS; int32_t lino = 0; if (pSBf->status == SBF_INVALID) { - code = TSDB_CODE_FAILED; + code = TSDB_CODE_OUT_OF_BUFFER; QUERY_CHECK_CODE(code, lino, _end); } uint64_t h1 = (uint64_t)pSBf->hashFn1(keyBuf, len); @@ -153,7 +153,7 @@ static int32_t tScalableBfAddFilter(SScalableBf* pSBf, uint64_t expectedEntries, int32_t code = TSDB_CODE_SUCCESS; int32_t lino = 0; if (taosArrayGetSize(pSBf->bfArray) >= pSBf->maxBloomFilters) { - code = TSDB_CODE_FAILED; + code = TSDB_CODE_OUT_OF_BUFFER; QUERY_CHECK_CODE(code, lino, _error); } @@ -163,7 +163,7 @@ static int32_t tScalableBfAddFilter(SScalableBf* pSBf, uint64_t expectedEntries, if (taosArrayPush(pSBf->bfArray, &pNormalBf) == NULL) { tBloomFilterDestroy(pNormalBf); - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; QUERY_CHECK_CODE(code, lino, _error); } pSBf->numBits += pNormalBf->numBits; @@ -217,7 +217,7 @@ int32_t tScalableBfDecode(SDecoder* pDecoder, SScalableBf** ppSBf) { pSBf->bfArray = NULL; int32_t size = 0; if (tDecodeI32(pDecoder, &size) < 0) { - code = TSDB_CODE_FAILED; + code = terrno; QUERY_CHECK_CODE(code, lino, _error); } if (size == 0) { @@ -242,19 +242,19 @@ int32_t tScalableBfDecode(SDecoder* pDecoder, SScalableBf** ppSBf) { } } if (tDecodeU32(pDecoder, &pSBf->growth) < 0) { - code = TSDB_CODE_FAILED; + code = terrno; QUERY_CHECK_CODE(code, lino, _error); } if (tDecodeU64(pDecoder, &pSBf->numBits) < 0) { - code = TSDB_CODE_FAILED; + code = terrno; QUERY_CHECK_CODE(code, lino, _error); } if (tDecodeU32(pDecoder, &pSBf->maxBloomFilters) < 0) { - code = TSDB_CODE_FAILED; + code = terrno; QUERY_CHECK_CODE(code, lino, _error); } if (tDecodeI8(pDecoder, &pSBf->status) < 0) { - code = TSDB_CODE_FAILED; + code = terrno; QUERY_CHECK_CODE(code, lino, _error); } (*ppSBf) = pSBf; From 4fd86887953857702971b7ca485e90aac82e0ae3 Mon Sep 17 00:00:00 2001 From: wangjiaming0909 <604227650@qq.com> Date: Fri, 9 Aug 2024 14:43:50 +0800 Subject: [PATCH 13/34] postfix exchange operator blocking due to addref failed --- source/libs/executor/src/exchangeoperator.c | 6 ++++-- source/libs/executor/src/tfill.c | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/libs/executor/src/exchangeoperator.c b/source/libs/executor/src/exchangeoperator.c index 78c0d939ad..5afae596a4 100644 --- a/source/libs/executor/src/exchangeoperator.c +++ b/source/libs/executor/src/exchangeoperator.c @@ -390,11 +390,13 @@ static int32_t initExchangeOperator(SExchangePhysiNode* pExNode, SExchangeInfo* } initLimitInfo(pExNode->node.pLimit, pExNode->node.pSlimit, &pInfo->limitInfo); - pInfo->self = taosAddRef(exchangeObjRefPool, pInfo); - if (pInfo->self < 0) { + int64_t refId = taosAddRef(exchangeObjRefPool, pInfo); + if (refId < 0) { int32_t code = terrno; qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); return code; + } else { + pInfo->self = refId; } return initDataSource(numOfSources, pInfo, id); diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c index 3158c85987..957a5d1d2e 100644 --- a/source/libs/executor/src/tfill.c +++ b/source/libs/executor/src/tfill.c @@ -758,7 +758,10 @@ SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfFillExpr, SExprIn SValueNode* pv = (SValueNode*)nodesListGetNode(pValNode->pNodeList, index); QUERY_CHECK_NULL(pv, code, lino, _end, terrno); - nodesValueNodeToVariant(pv, &pFillCol[i].fillVal); + code = nodesValueNodeToVariant(pv, &pFillCol[i].fillVal); + } + if (TSDB_CODE_SUCCESS != code) { + goto _end; } } pFillCol->numOfFillExpr = numOfFillExpr; From acf17054d3b65443d99115ab273fa7b13b92e537 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Fri, 9 Aug 2024 15:20:33 +0800 Subject: [PATCH 14/34] fix: possible error handle in syncPipeline.c --- source/libs/sync/src/syncPipeline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/libs/sync/src/syncPipeline.c b/source/libs/sync/src/syncPipeline.c index ef2cbece79..782d97f789 100644 --- a/source/libs/sync/src/syncPipeline.c +++ b/source/libs/sync/src/syncPipeline.c @@ -892,7 +892,7 @@ int32_t syncLogReplRecover(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEn if (pMsg->matchIndex < pNode->pLogBuf->matchIndex) { code = syncLogReplGetPrevLogTerm(pMgr, pNode, index + 1, &term); - if (term < 0 && (errno == ENFILE || errno == EMFILE)) { + if (term < 0 && (errno == ENFILE || errno == EMFILE || errno == ENOENT)) { sError("vgId:%d, failed to get prev log term since %s. index:%" PRId64, pNode->vgId, tstrerror(code), index + 1); TAOS_RETURN(code); } From fe48c405709589a2ab930d37fbf8c35bd5b5eaba Mon Sep 17 00:00:00 2001 From: gccgdb1234 Date: Fri, 9 Aug 2024 15:49:54 +0800 Subject: [PATCH 15/34] doc: correct join error --- docs/zh/14-reference/03-taos-sql/30-join.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/14-reference/03-taos-sql/30-join.md b/docs/zh/14-reference/03-taos-sql/30-join.md index c0daeb41c0..60b634d310 100644 --- a/docs/zh/14-reference/03-taos-sql/30-join.md +++ b/docs/zh/14-reference/03-taos-sql/30-join.md @@ -202,7 +202,7 @@ SELECT ... FROM table_name1 LEFT|RIGHT ASOF JOIN table_name2 [ON ...] [JLIMIT jl 表 d1001 电压值大于 220V 且表 d1002 中同一时刻或稍早前最后时刻出现电压大于 220V 的时间及各自的电压值: ```sql -SELECT a.ts, a.voltage, a.ts, b.voltage FROM d1001 a LEFT ASOF JOIN d1002 b ON a.ts >= b.ts where a.voltage > 220 and b.voltage > 220 +SELECT a.ts, a.voltage, b.ts, b.voltage FROM d1001 a LEFT ASOF JOIN d1002 b ON a.ts >= b.ts where a.voltage > 220 and b.voltage > 220 ``` ### Left/Right Window Join From 2553bb1745bd1ad308e548c58386000c8305492e Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Fri, 9 Aug 2024 15:51:58 +0800 Subject: [PATCH 16/34] fix: remove an invalid assert in syncMain.c --- source/libs/sync/src/syncMain.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 171b73eba7..fd1d3e371e 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -1287,7 +1287,7 @@ SSyncNode* syncNodeOpen(SSyncInfo* pSyncInfo, int32_t vnodeVersion) { } // tools - (void)syncRespMgrCreate(pSyncNode, SYNC_RESP_TTL_MS, &pSyncNode->pSyncRespMgr); // TODO: check return value + (void)syncRespMgrCreate(pSyncNode, SYNC_RESP_TTL_MS, &pSyncNode->pSyncRespMgr); // TODO: check return value if (pSyncNode->pSyncRespMgr == NULL) { sError("vgId:%d, failed to create SyncRespMgr", pSyncNode->vgId); goto _error; @@ -1407,7 +1407,8 @@ int32_t syncNodeRestore(SSyncNode* pSyncNode) { pSyncNode->commitIndex = TMAX(pSyncNode->commitIndex, commitIndex); sInfo("vgId:%d, restore sync until commitIndex:%" PRId64, pSyncNode->vgId, pSyncNode->commitIndex); - if (pSyncNode->fsmState != SYNC_FSM_STATE_INCOMPLETE && (code = syncLogBufferCommit(pSyncNode->pLogBuf, pSyncNode, pSyncNode->commitIndex)) < 0) { + if (pSyncNode->fsmState != SYNC_FSM_STATE_INCOMPLETE && + (code = syncLogBufferCommit(pSyncNode->pLogBuf, pSyncNode, pSyncNode->commitIndex)) < 0) { TAOS_RETURN(code); } @@ -2187,7 +2188,7 @@ void syncNodeCandidate2Leader(SSyncNode* pSyncNode) { } SyncIndex lastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore); - ASSERT(lastIndex >= 0); + // ASSERT(lastIndex >= 0); sInfo("vgId:%d, become leader. term:%" PRId64 ", commit index:%" PRId64 ", last index:%" PRId64 "", pSyncNode->vgId, raftStoreGetTerm(pSyncNode), pSyncNode->commitIndex, lastIndex); } From 64874f6e40287fe676a0bf85db0c5ecf6446d23d Mon Sep 17 00:00:00 2001 From: sima Date: Fri, 9 Aug 2024 16:00:05 +0800 Subject: [PATCH 17/34] fix:[TD-31355] use correct way to handle error. --- source/libs/scalar/src/filter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index e5d0fe594a..729a3ff840 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -2908,6 +2908,7 @@ int32_t filterGenerateColRange(SFilterInfo *info, SFilterGroupCtx **gRes, int32_ info->colRangeNum = colNum; info->colRange = taosMemoryCalloc(colNum, POINTER_BYTES); if (info->colRange == NULL) { + info->colRangeNum = 0; FLT_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); } From 3b99e077ef47cf6acb8f5c44de4f38cf71cee64f Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Fri, 9 Aug 2024 16:57:10 +0800 Subject: [PATCH 18/34] fix return error --- source/libs/stream/src/streamBackendRocksdb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/libs/stream/src/streamBackendRocksdb.c b/source/libs/stream/src/streamBackendRocksdb.c index ee87d3b897..83e55791d2 100644 --- a/source/libs/stream/src/streamBackendRocksdb.c +++ b/source/libs/stream/src/streamBackendRocksdb.c @@ -1452,8 +1452,14 @@ int32_t taskDbBuildSnap(void* arg, SArray* pSnap) { code = TSDB_CODE_OUT_OF_MEMORY; break; } - (void)taosArrayPush(pSnap, &snap); + if (taosArrayPush(pSnap, &snap) == NULL) { + taskDbUnRefChkp(pTaskDb, pTaskDb->chkpId); + taskDbRemoveRef(pTaskDb); + code = terrno; + break; + } + taskDbRemoveRef(pTaskDb); pIter = taosHashIterate(pMeta->pTaskDbUnique, pIter); } streamMutexUnlock(&pMeta->backendMutex); From 105594848cfd15f2f51c4b367219333618b047b4 Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Fri, 9 Aug 2024 17:00:18 +0800 Subject: [PATCH 19/34] fix(tsdb/cache): return oom if array or push failed --- source/dnode/vnode/src/tsdb/tsdbCache.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbCache.c b/source/dnode/vnode/src/tsdb/tsdbCache.c index b7e3bb6a07..1216f0da81 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCache.c +++ b/source/dnode/vnode/src/tsdb/tsdbCache.c @@ -1703,8 +1703,14 @@ int32_t tsdbCacheGetBatch(STsdb *pTsdb, tb_uid_t uid, SArray *pLastArray, SCache if (!remainCols) { remainCols = taosArrayInit(num_keys, sizeof(SIdxKey)); + if (!remainCols) { + TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY); + } } - (void)taosArrayPush(remainCols, &(SIdxKey){i, key}); + if (NULL == taosArrayPush(remainCols, &(SIdxKey){i, key})) { + taosArrayDestroy(remainCols); + TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY); + }; } } From b8cd001dfb4c114cdb6307ca1cb5284c97469ee4 Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Fri, 9 Aug 2024 17:06:35 +0800 Subject: [PATCH 20/34] fix(meta/query): return oom with null ctb cursor --- source/dnode/vnode/src/meta/metaQuery.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index 27a4179172..576324d7c2 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -1441,6 +1441,9 @@ int32_t metaGetTableTagsByUids(void *pVnode, int64_t suid, SArray *uidList) { int32_t metaGetTableTags(void *pVnode, uint64_t suid, SArray *pUidTagInfo) { SMCtbCursor *pCur = metaOpenCtbCursor(pVnode, suid, 1); + if (!pCur) { + TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY); + } // If len > 0 means there already have uids, and we only want the // tags of the specified tables, of which uid in the uid list. Otherwise, all table tags are retrieved and kept From 2d2ba4fd2905c481e14cd3ca564a7e075065fbf3 Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Fri, 9 Aug 2024 17:09:19 +0800 Subject: [PATCH 21/34] fix(meta/query): return oom if malloc failed --- source/dnode/vnode/src/meta/metaQuery.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index 27a4179172..f5b03b340e 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -1234,6 +1234,9 @@ int32_t metaFilterTableIds(void *pVnode, SMetaFltParam *arg, SArray *pUids) { SIdxCursor *pCursor = NULL; pCursor = (SIdxCursor *)taosMemoryCalloc(1, sizeof(SIdxCursor)); + if (!pCursor) { + TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY); + } pCursor->pMeta = pMeta; pCursor->suid = param->suid; pCursor->cid = param->cid; From 0035c1b06a577f2b14229599db19d341cd0a01b0 Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Fri, 9 Aug 2024 17:13:37 +0800 Subject: [PATCH 22/34] fix(meta/query): return oom if malloc failed --- source/dnode/vnode/src/meta/metaQuery.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index 27a4179172..ffa4067ab9 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -1427,6 +1427,11 @@ int32_t metaGetTableTagsByUids(void *pVnode, int64_t suid, SArray *uidList) { int32_t len = 0; if (metaGetTableTagByUid(pMeta, suid, p->uid, &val, &len, false) == 0) { p->pTagVal = taosMemoryMalloc(len); + if (!p->pTagVal) { + if (isLock) metaULock(pMeta); + + TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY); + } memcpy(p->pTagVal, val, len); tdbFree(val); } else { From 353bcc5a4754225269419a8d498c32f3833b85e4 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 9 Aug 2024 17:58:01 +0800 Subject: [PATCH 23/34] doc: adjust typo --- docs/zh/08-develop/09-udf.md | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md index 700bbb2ae0..4606e968d9 100644 --- a/docs/zh/08-develop/09-udf.md +++ b/docs/zh/08-develop/09-udf.md @@ -410,7 +410,7 @@ def finish(buf: bytes) -> output_type: #### 示例一 编写一个只接收一个整数的 UDF 函数: 输入 n, 输出 ln(n^2 + 1)。 -首先编写一个 Python 文件,存在系统某个目录,比如 /root/udf/myfun.py 内容如下 +首先编写一个 Python 文件,存在系统某个目录,比如 /root/udf/myfun.py 内容如下。 ```python from math import log @@ -426,23 +426,23 @@ def process(block): return [log(block.data(i, 0) ** 2 + 1) for i in range(rows)] ``` -这个文件包含 3 个函数, init 和 destroy 都是空函数,它们是 UDF 的生命周期函数,即使什么都不做也要定义。最关键的是 process 函数, 它接受一个数据块,这个数据块对象有两个方法: +这个文件包含 3 个函数, init 和 destroy 都是空函数,它们是 UDF 的生命周期函数,即使什么都不做也要定义。最关键的是 process 函数, 它接受一个数据块,这个数据块对象有两个方法。 1. shape() 返回数据块的行数和列数 2. data(i, j) 返回 i 行 j 列的数据 -标量函数的 process 方法传人的数据块有多少行,就需要返回多少个数据。上述代码中我们忽略的列数,因为我们只想对每行的第一个数做计算。 -接下来我们创建对应的 UDF 函数,在 TDengine CLI 中执行下面语句: +标量函数的 process 方法传入的数据块有多少行,就需要返回多少行数据。上述代码忽略列数,因为只需对每行的第一个数做计算。 +接下来我建对应的 UDF 函数,在 TDengine CLI 中执行下面语句。 ```sql create function myfun as '/root/udf/myfun.py' outputtype double language 'Python' ``` -其输出如下 +其输出如下。 ```shell taos> create function myfun as '/root/udf/myfun.py' outputtype double language 'Python'; Create OK, 0 row(s) affected (0.005202s) ``` -看起来很顺利,接下来 show 一下系统中所有的自定义函数,确认创建成功: +看起来很顺利,接下来 show 一下系统中所有的自定义函数,确认创建成功。 ```text taos> show functions; @@ -452,7 +452,7 @@ taos> show functions; Query OK, 1 row(s) in set (0.005767s) ``` -接下来就来测试一下这个函数,测试之前先执行下面的 SQL 命令,制造些测试数据,在 TDengine CLI 中执行下述命令 +接下来就来测试一下这个函数,测试之前先执行下面的 SQL 命令,制造些测试数据,在 TDengine CLI 中执行下述命令。 ```sql create database test; @@ -462,7 +462,7 @@ insert into t values('2023-05-03 08:09:10', 2, 3, 4); insert into t values('2023-05-10 07:06:05', 3, 4, 5); ``` -测试 myfun 函数: +测试 myfun 函数。 ```sql taos> select myfun(v1, v2) from t; @@ -471,13 +471,13 @@ DB error: udf function execution failure (0.011088s) ``` 不幸的是执行失败了,什么原因呢? -查看 udfd 进程的日志 +查看 udfd 进程的日志。 ```shell tail -10 /var/log/taos/udfd.log ``` -发现以下错误信息: +发现以下错误信息。 ```text 05/24 22:46:28.733545 01665799 UDF ERROR can not load library libtaospyudf.so. error: operation not permitted @@ -486,7 +486,7 @@ tail -10 /var/log/taos/udfd.log 错误很明确:没有加载到 Python 插件 libtaospyudf.so,如果遇到此错误,请参考前面的准备环境一节。 -修复环境错误后再次执行,如下: +修复环境错误后再次执行,如下。 ```sql taos> select myfun(v1) from t; @@ -501,7 +501,7 @@ taos> select myfun(v1) from t; #### 示例二 -上面的 myfun 虽然测试测试通过了,但是有两个缺点: +上面的 myfun 虽然测试测试通过了,但是有两个缺点。 1. 这个标量函数只接受 1 列数据作为输入,如果用户传入了多列也不会抛异常。 @@ -515,7 +515,7 @@ taos> select myfun(v1, v2) from t; ``` 2. 没有处理 null 值。我们期望如果输入有 null,则会抛异常终止执行。 -因此 process 函数改进如下: +因此 process 函数改进如下。 ```python def process(block): @@ -525,13 +525,13 @@ def process(block): return [ None if block.data(i, 0) is None else log(block.data(i, 0) ** 2 + 1) for i in range(rows)] ``` -然后执行下面的语句更新已有的 UDF: +然后执行下面的语句更新已有的 UDF。 ```sql create or replace function myfun as '/root/udf/myfun.py' outputtype double language 'Python'; ``` -再传入 myfun 两个参数,就会执行失败了 +再传入 myfun 两个参数,就会执行失败了。 ```sql taos> select myfun(v1, v2) from t; @@ -539,7 +539,7 @@ taos> select myfun(v1, v2) from t; DB error: udf function execution failure (0.014643s) ``` -但遗憾的是我们自定义的异常信息没有展示给用户,而是在插件的日志文件 /var/log/taos/taospyudf.log 中: +但遗憾的是我们自定义的异常信息没有展示给用户,而是在插件的日志文件 /var/log/taos/taospyudf.log 中。 ```text 2023-05-24 23:21:06.790 ERROR [1666188] [doPyUdfScalarProc@507] call pyUdfScalar proc function. context 0x7faade26d180. error: Exception: require 1 parameter but given 2 @@ -555,7 +555,7 @@ At: #### 示例三 编写一个 UDF:输入(x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和: 1 * x1 + 2 * x2 + ... + n * xn。如果 x1 至 xn 中包含 null,则结果为 null。 -这个示例与示例一的区别是,可以接受任意多列作为输入,且要处理每一列的值。编写 UDF 文件 /root/udf/nsum.py: +这个示例与示例一的区别是,可以接受任意多列作为输入,且要处理每一列的值。编写 UDF 文件 /root/udf/nsum.py。 ```python def init(): @@ -581,13 +581,13 @@ def process(block): return result ``` -创建 UDF: +创建 UDF。 ```sql create function nsum as '/root/udf/nsum.py' outputtype double language 'Python'; ``` -测试 UDF: +测试 UDF。 ```sql taos> insert into t values('2023-05-25 09:09:15', 6, null, 8); @@ -606,13 +606,13 @@ Query OK, 4 row(s) in set (0.010653s) #### 示例四 编写一个 UDF,输入一个时间戳,输出距离这个时间最近的下一个周日。比如今天是 2023-05-25, 则下一个周日是 2023-05-28。 -完成这个函数要用到第三方库 momen。先安装这个库: +完成这个函数要用到第三方库 momen。先安装这个库。 ```shell pip3 install moment ``` -然后编写 UDF 文件 /root/udf/nextsunday.py +然后编写 UDF 文件 /root/udf/nextsunday.py。 ```python import moment @@ -636,13 +636,13 @@ def process(block): for i in range(rows)] ``` -UDF 框架会将 TDengine 的 timestamp 类型映射为 Python 的 int 类型,所以这个函数只接受一个表示毫秒数的整数。process 方法先做参数检查,然后用 moment 包替换时间的星期为星期日,最后格式化输出。输出的字符串长度是固定的 10 个字符长,因此可以这样创建 UDF 函数: +UDF 框架会将 TDengine 的 timestamp 类型映射为 Python 的 int 类型,所以这个函数只接受一个表示毫秒数的整数。process 方法先做参数检查,然后用 moment 包替换时间的星期为星期日,最后格式化输出。输出的字符串长度是固定的 10 个字符长,因此可以这样创建 UDF 函数。 ```sql create function nextsunday as '/root/udf/nextsunday.py' outputtype binary(10) language 'Python'; ``` -此时测试函数,如果你是用 systemctl 启动的 taosd,肯定会遇到错误: +此时测试函数,如果你是用 systemctl 启动的 taosd,肯定会遇到错误。 ```sql taos> select ts, nextsunday(ts) from t; @@ -655,7 +655,7 @@ DB error: udf function execution failure (1.123615s) 2023-05-25 11:42:34.541 ERROR [1679419] [PyUdf::PyUdf@217] py udf load module failure. error ModuleNotFoundError: No module named 'moment' ``` -这是因为 “moment” 所在位置不在 python udf 插件默认的库搜索路径中。怎么确认这一点呢?通过以下命令搜索 taospyudf.log: +这是因为 “moment” 所在位置不在 python udf 插件默认的库搜索路径中。怎么确认这一点呢?通过以下命令搜索 taospyudf.log。 ```shell grep 'sys path' taospyudf.log | tail -1 @@ -668,7 +668,7 @@ grep 'sys path' taospyudf.log | tail -1 ``` 发现 python udf 插件默认搜索的第三方库安装路径是: /lib/python3/dist-packages,而 moment 默认安装到了 /usr/local/lib/python3.8/dist-packages。下面我们修改 python udf 插件默认的库搜索路径。 -先打开 python3 命令行,查看当前的 sys.path +先打开 python3 命令行,查看当前的 sys.path。 ```python >>> import sys @@ -676,13 +676,13 @@ grep 'sys path' taospyudf.log | tail -1 '/usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages' ``` -复制上面脚本的输出的字符串,然后编辑 /var/taos/taos.cfg 加入以下配置: +复制上面脚本的输出的字符串,然后编辑 /var/taos/taos.cfg 加入以下配置。 ```shell UdfdLdLibPath /usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages ``` -保存后执行 systemctl restart taosd, 再测试就不报错了: +保存后执行 systemctl restart taosd, 再测试就不报错了。 ```sql taos> select ts, nextsunday(ts) from t; @@ -698,7 +698,7 @@ Query OK, 4 row(s) in set (1.011474s) #### 示例五 编写一个聚合函数,计算某一列最大值和最小值的差。 -聚合函数与标量函数的区别是:标量函数是多行输入对应多个输出,聚合函数是多行输入对应一个输出。聚合函数的执行过程有点像经典的 map-reduce 框架的执行过程,框架把数据分成若干块,每个 mapper 处理一个块,reducer 再把 mapper 的结果做聚合。不一样的地方在于,对于 TDengine Python UDF 中的 reduce 函数既有 map 的功能又有 reduce 的功能。reduce 函数接受两个参数:一个是自己要处理的数据,一个是别的任务执行 reduce 函数的处理结果。如下面的示例 /root/udf/myspread.py: +聚合函数与标量函数的区别是:标量函数是多行输入对应多个输出,聚合函数是多行输入对应一个输出。聚合函数的执行过程有点像经典的 map-reduce 框架的执行过程,框架把数据分成若干块,每个 mapper 处理一个块,reducer 再把 mapper 的结果做聚合。不一样的地方在于,对于 TDengine Python UDF 中的 reduce 函数既有 map 的功能又有 reduce 的功能。reduce 函数接受两个参数:一个是自己要处理的数据,一个是别的任务执行 reduce 函数的处理结果。如下面的示例 /root/udf/myspread.py。 ```python import io @@ -747,20 +747,20 @@ def finish(buf): return max_number - min_number ``` -在这个示例中我们不光定义了一个聚合函数,还添加记录执行日志的功能,讲解如下: +在这个示例中我们不光定义了一个聚合函数,还添加记录执行日志的功能,讲解如下。 1. init 函数不再是空函数,而是打开了一个文件用于写执行日志 2. log 函数是记录日志的工具,自动将传入的对象转成字符串,加换行符输出 3. destroy 函数用来在执行结束关闭文件 4. start 返回了初始的 buffer,用来存聚合函数的中间结果,我们把最大值初始化为负无穷大,最小值初始化为正无穷大 5. reduce 处理每个数据块并聚合结果 6. finish 函数将最终的 buffer 转换成最终的输出 -执行下面的 SQL语句创建对应的 UDF: +执行下面的 SQL语句创建对应的 UDF。 ```sql create or replace aggregate function myspread as '/root/udf/myspread.py' outputtype double bufsize 128 language 'Python'; ``` -这个 SQL 语句与创建标量函数的 SQL 语句有两个重要区别: +这个 SQL 语句与创建标量函数的 SQL 语句有两个重要区别。 1. 增加了 aggregate 关键字 2. 增加了 bufsize 关键字,用来指定存储中间结果的内存大小,这个数值可以大于实际使用的数值。本例中间结果是两个浮点数组成的 tuple,序列化后实际占用大小只有 32 个字节,但指定的 bufsize 是128,可以用 python 命令行打印实际占用的字节数 From 8790d5c02b7f4de72249e4a83ba54bdc33c9215e Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 9 Aug 2024 17:59:01 +0800 Subject: [PATCH 24/34] doc: minor changes --- docs/zh/08-develop/09-udf.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md index 4606e968d9..bc62dbfa3c 100644 --- a/docs/zh/08-develop/09-udf.md +++ b/docs/zh/08-develop/09-udf.md @@ -430,7 +430,7 @@ def process(block): 1. shape() 返回数据块的行数和列数 2. data(i, j) 返回 i 行 j 列的数据 标量函数的 process 方法传入的数据块有多少行,就需要返回多少行数据。上述代码忽略列数,因为只需对每行的第一个数做计算。 -接下来我建对应的 UDF 函数,在 TDengine CLI 中执行下面语句。 +接下来创建对应的 UDF 函数,在 TDengine CLI 中执行下面语句。 ```sql create function myfun as '/root/udf/myfun.py' outputtype double language 'Python' From 5e10f461ad1c8b0e3ce8556372a2bf08e2eebd44 Mon Sep 17 00:00:00 2001 From: gccgdb1234 Date: Fri, 9 Aug 2024 18:01:45 +0800 Subject: [PATCH 25/34] docs: reorganize the order of create database parameters --- .../14-reference/03-taos-sql/02-database.md | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/zh/14-reference/03-taos-sql/02-database.md b/docs/zh/14-reference/03-taos-sql/02-database.md index 8a366011ae..d2e9ba0646 100644 --- a/docs/zh/14-reference/03-taos-sql/02-database.md +++ b/docs/zh/14-reference/03-taos-sql/02-database.md @@ -13,26 +13,26 @@ database_options: database_option ... database_option: { - BUFFER value + VGROUPS value + | PRECISION {'ms' | 'us' | 'ns'} + | REPLICA value + | BUFFER value + | PAGES value + | PAGESIZE value | CACHEMODEL {'none' | 'last_row' | 'last_value' | 'both'} | CACHESIZE value | COMP {0 | 1 | 2} | DURATION value - | WAL_FSYNC_PERIOD value | MAXROWS value | MINROWS value | KEEP value - | PAGES value - | PAGESIZE value - | PRECISION {'ms' | 'us' | 'ns'} - | REPLICA value - | WAL_LEVEL {1 | 2} - | VGROUPS value - | SINGLE_STABLE {0 | 1} | STT_TRIGGER value + | SINGLE_STABLE {0 | 1} | TABLE_PREFIX value | TABLE_SUFFIX value | TSDB_PAGESIZE value + | WAL_LEVEL {1 | 2} + | WAL_FSYNC_PERIOD value | WAL_RETENTION_PERIOD value | WAL_RETENTION_SIZE value } @@ -40,7 +40,14 @@ database_option: { ### 参数说明 +- VGROUPS:数据库中初始 vgroup 的数目。 +- PRECISION:数据库的时间戳精度。ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认 ms 毫秒。 +- REPLICA:表示数据库副本数,取值为 1、2 或 3,默认为 1; 2 仅在企业版 3.3.0.0 及以后版本中可用。在集群中使用,副本数必须小于或等于 DNODE 的数目。且使用时存在以下限制: + - 暂不支持对双副本数据库相关 Vgroup 进行 SPLITE VGROUP 或 REDISTRIBUTE VGROUP 操作 + - 单副本数据库可变更为双副本数据库,但不支持从双副本变更为其它副本数,也不支持从三副本变更为双副本 - BUFFER: 一个 VNODE 写入内存池大小,单位为 MB,默认为 256,最小为 3,最大为 16384。 +- PAGES:一个 VNODE 中元数据存储引擎的缓存页个数,默认为 256,最小 64。一个 VNODE 元数据存储占用 PAGESIZE \* PAGES,默认情况下为 1MB 内存。 +- PAGESIZE:一个 VNODE 中元数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB 到 16 MB。 - CACHEMODEL:表示是否在内存中缓存子表的最近数据。默认为 none。 - none:表示不缓存。 - last_row:表示缓存子表最近一行数据。这将显著改善 LAST_ROW 函数的性能表现。 @@ -53,27 +60,20 @@ database_option: { - 1:表示一阶段压缩。 - 2:表示两阶段压缩。 - DURATION:数据文件存储数据的时间跨度。可以使用加单位的表示形式,如 DURATION 100h、DURATION 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。不加时间单位时默认单位为天,如 DURATION 50 表示 50 天。 -- WAL_FSYNC_PERIOD:当 WAL_LEVEL 参数设置为 2 时,用于设置落盘的周期。默认为 3000,单位毫秒。最小为 0,表示每次写入立即落盘;最大为 180000,即三分钟。 - MAXROWS:文件块中记录的最大条数,默认为 4096 条。 - MINROWS:文件块中记录的最小条数,默认为 100 条。 - KEEP:表示数据文件保存的天数,缺省值为 3650,取值范围 [1, 365000],且必须大于或等于3倍的 DURATION 参数值。数据库会自动删除保存时间超过 KEEP 值的数据。KEEP 可以使用加单位的表示形式,如 KEEP 100h、KEEP 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。也可以不写单位,如 KEEP 50,此时默认单位为天。企业版支持[多级存储](https://docs.taosdata.com/tdinternal/arch/#%E5%A4%9A%E7%BA%A7%E5%AD%98%E5%82%A8)功能, 因此, 可以设置多个保存时间(多个以英文逗号分隔,最多 3 个,满足 keep 0 \<= keep 1 \<= keep 2,如 KEEP 100h,100d,3650d); 社区版不支持多级存储功能(即使配置了多个保存时间, 也不会生效, KEEP 会取最大的保存时间)。 -- PAGES:一个 VNODE 中元数据存储引擎的缓存页个数,默认为 256,最小 64。一个 VNODE 元数据存储占用 PAGESIZE \* PAGES,默认情况下为 1MB 内存。 -- PAGESIZE:一个 VNODE 中元数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB 到 16 MB。 -- PRECISION:数据库的时间戳精度。ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认 ms 毫秒。 -- REPLICA:表示数据库副本数,取值为 1、2 或 3,默认为 1; 2 仅在企业版 3.3.0.0 及以后版本中可用。在集群中使用,副本数必须小于或等于 DNODE 的数目。且使用时存在以下限制: - - 暂不支持对双副本数据库相关 Vgroup 进行 SPLITE VGROUP 或 REDISTRIBUTE VGROUP 操作 - - 单副本数据库可变更为双副本数据库,但不支持从双副本变更为其它副本数,也不支持从三副本变更为双副本 -- WAL_LEVEL:WAL 级别,默认为 1。 - - 1:写 WAL,但不执行 fsync。 - - 2:写 WAL,而且执行 fsync。 -- VGROUPS:数据库中初始 vgroup 的数目。 +- STT_TRIGGER:表示落盘文件触发文件合并的个数。默认为 1,范围 1 到 16。对于少表高频场景,此参数建议使用默认配置,或较小的值;而对于多表低频场景,此参数建议配置较大的值。 - SINGLE_STABLE:表示此数据库中是否只可以创建一个超级表,用于超级表列非常多的情况。 - 0:表示可以创建多张超级表。 - 1:表示只可以创建一张超级表。 -- STT_TRIGGER:表示落盘文件触发文件合并的个数。默认为 1,范围 1 到 16。对于少表高频场景,此参数建议使用默认配置,或较小的值;而对于多表低频场景,此参数建议配置较大的值。 - TABLE_PREFIX:当其为正值时,在决定把一个表分配到哪个 vgroup 时要忽略表名中指定长度的前缀;当其为负值时,在决定把一个表分配到哪个 vgroup 时只使用表名中指定长度的前缀;例如,假定表名为 "v30001",当 TSDB_PREFIX = 2 时 使用 "0001" 来决定分配到哪个 vgroup ,当 TSDB_PREFIX = -2 时使用 "v3" 来决定分配到哪个 vgroup - TABLE_SUFFIX:当其为正值时,在决定把一个表分配到哪个 vgroup 时要忽略表名中指定长度的后缀;当其为负值时,在决定把一个表分配到哪个 vgroup 时只使用表名中指定长度的后缀;例如,假定表名为 "v30001",当 TSDB_SUFFIX = 2 时 使用 "v300" 来决定分配到哪个 vgroup ,当 TSDB_SUFFIX = -2 时使用 "01" 来决定分配到哪个 vgroup。 - TSDB_PAGESIZE:一个 VNODE 中时序数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB到 16 MB。 +- WAL_LEVEL:WAL 级别,默认为 1。 + - 1:写 WAL,但不执行 fsync。 + - 2:写 WAL,而且执行 fsync。 +- WAL_FSYNC_PERIOD:当 WAL_LEVEL 参数设置为 2 时,用于设置落盘的周期。默认为 3000,单位毫秒。最小为 0,表示每次写入立即落盘;最大为 180000,即三分钟。 - WAL_RETENTION_PERIOD: 为了数据订阅消费,需要WAL日志文件额外保留的最大时长策略。WAL日志清理,不受订阅客户端消费状态影响。单位为 s。默认为 3600,表示在 WAL 保留最近 3600 秒的数据,请根据数据订阅的需要修改这个参数为适当值。 - WAL_RETENTION_SIZE:为了数据订阅消费,需要WAL日志文件额外保留的最大累计大小策略。单位为 KB。默认为 0,表示累计大小无上限。 ### 创建数据库示例 From 43448bee6e21def9acd9ac4fdcbc4d8b9c58e6ad Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Fri, 9 Aug 2024 18:20:50 +0800 Subject: [PATCH 26/34] fix doc issue --- .../com/taos/example/WSConnectExample.java | 48 +++++++-------- docs/zh/08-develop/02-sql.md | 2 +- .../01-components/12-tdinsight/index.mdx | 4 +- docs/zh/14-reference/05-connector/index.md | 58 ++++++++++--------- .../20-third-party/03-visual/01-grafana.mdx | 46 ++++++++++----- examples/JDBC/connectionPools/pom.xml | 2 +- .../java/com/taosdata/example/DruidDemo.java | 2 +- .../example/pool/DruidPoolBuilder.java | 2 +- .../example/pool/HikariCpBuilder.java | 2 +- .../src/main/resources/proxool.xml | 2 +- 10 files changed, 94 insertions(+), 74 deletions(-) diff --git a/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java b/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java index f920e77037..21f184b45a 100644 --- a/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java +++ b/docs/examples/java/src/main/java/com/taos/example/WSConnectExample.java @@ -8,31 +8,33 @@ import java.sql.SQLException; import java.util.Properties; public class WSConnectExample { -// ANCHOR: main -public static void main(String[] args) throws SQLException { - // use - // String jdbcUrl = "jdbc:TAOS-RS://localhost:6041/dbName?user=root&password=taosdata&batchfetch=true"; - // if you want to connect a specified database named "dbName". - String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata&batchfetch=true"; - Properties connProps = new Properties(); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true"); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT, "true"); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + // ANCHOR: main + public static void main(String[] args) throws SQLException { + // use + // String jdbcUrl = + // "jdbc:TAOS-RS://localhost:6041/dbName?user=root&password=taosdata&batchfetch=true"; + // if you want to connect a specified database named "dbName". + String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata&batchfetch=true"; + Properties connProps = new Properties(); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT, "true"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); - try (Connection conn = DriverManager.getConnection(jdbcUrl, connProps)){ - System.out.println("Connected to " + jdbcUrl + " successfully."); + try (Connection conn = DriverManager.getConnection(jdbcUrl, connProps)) { + System.out.println("Connected to " + jdbcUrl + " successfully."); - // you can use the connection for execute SQL here + // you can use the connection for execute SQL here - } catch (SQLException ex) { - // handle any errors, please refer to the JDBC specifications for detailed exceptions info - System.out.println("Failed to connect to " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage()); - throw ex; - } catch (Exception ex){ - System.out.println("Failed to connect to " + jdbcUrl + "; ErrMessage: " + ex.getMessage()); - throw ex; + } catch (SQLException ex) { + // handle any errors, please refer to the JDBC specifications for detailed + // exceptions info + System.out.println("Failed to connect to " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + + ex.getMessage()); + throw ex; + } catch (Exception ex) { + System.out.println("Failed to connect to " + jdbcUrl + "; ErrMessage: " + ex.getMessage()); + throw ex; + } } -} -// ANCHOR_END: main + // ANCHOR_END: main } diff --git a/docs/zh/08-develop/02-sql.md b/docs/zh/08-develop/02-sql.md index 3bebe5e7a4..3cad007078 100644 --- a/docs/zh/08-develop/02-sql.md +++ b/docs/zh/08-develop/02-sql.md @@ -90,7 +90,7 @@ curl --location -uroot:taosdata 'http://127.0.0.1:6041/rest/sql/power' \ -> **注意**:建议采用 `.` 的格式构造SQL语句,不推荐在应用中采用 `USE DBName`方式访问。 +> **注意**:建议采用 `.` 的格式构造SQL语句,不推荐在应用中采用 `USE DBName` 方式访问。 ## 插入数据 下面以智能电表为例,展示如何使用连接器执行 SQL 来插入数据到 `power` 数据库的 `meters` 超级表。样例使用 TDengine 自动建表 SQL 语法,写入 d1001 子表中 3 条数据,写入 d1002 子表中 1 条数据,然后打印出实际插入数据条数。 diff --git a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx index 2d4b69f46b..34a06e13c4 100644 --- a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx +++ b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx @@ -103,13 +103,13 @@ chmod +x TDinsight.sh 点击 `Save & Test` 进行测试,成功会提示:`TDengine Data source is working`。 -## 导入 TDengine V3 仪表盘 +## 导入 TDinsightV3 仪表盘 在配置 TDengine 数据源界面,点击 “Dashboards” tab,再点击 ”import” 导入 ”TDengine for 3.x” 仪表盘。 导入成功后可以进入这个 dashboard,在左上角 ”Log from“ 选项中选择 taosKeeper 中设置的记录监控指标的数据库就可以看到监控结果。 -## TDengine V3 仪表盘详情 +## TDinsightV3 仪表盘详情 TDinsight 仪表盘旨在提供 TDengine 相关资源的使用情况和状态,比如 dnodes、 mnodes、 vnodes 和数据库等。 主要分为集群状态、DNodes 概述、MNode 概述、请求、数据库、DNode 资源使用情况和 taosAdapter 监控信息。下面我们分别详细介绍。 diff --git a/docs/zh/14-reference/05-connector/index.md b/docs/zh/14-reference/05-connector/index.md index bc63bdff93..f9e1bd837d 100644 --- a/docs/zh/14-reference/05-connector/index.md +++ b/docs/zh/14-reference/05-connector/index.md @@ -13,7 +13,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 目前 TDengine 的原生接口连接器可支持的平台包括:X64/ARM64 等硬件平台,以及 Linux/Win64 等开发环境。对照矩阵如下: | **CPU** | **OS** | **Java** | **Python** | **Go** | **Node.js** | **C#** | **Rust** | C/C++ | -|---------------|-----------|----------|------------|--------|-------------|--------|----------|-------| +| ------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ----- | | **X86 64bit** | **Linux** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **Win64** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **macOS** | ● | ● | ● | ○ | ○ | ● | ● | @@ -28,14 +28,14 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 TDengine 版本更新往往会增加新的功能特性,列表中的连接器版本为连接器最佳适配版本。 -| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -|------------------------|----------|--------------------------------------|------------|---------------|-----------------|----------| -| **3.3.0.0 及以上** | 3.3.0及以上 | taospy 2.7.15及以上,taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 | -| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 | -| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | -| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | +| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +| ---------------------- | ----------- | ------------------------------------------- | ------------ | ------------- | --------------- | -------- | +| **3.3.0.0 及以上** | 3.3.0及以上 | taospy 2.7.15及以上,taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 | +| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 | +| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | +| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | ## 功能特性 @@ -43,32 +43,36 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器 ### 使用原生接口(taosc) -| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -|----------------|----------|------------|--------|--------|-------------|----------| -| **连接管理** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 不支持 | 支持 | +| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Rust** | +| ------------------- | -------- | ---------- | ------ | ------ | -------- | +| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | +| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | +| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | +| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | :::info 由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。 ::: -### 使用 http (REST 或 WebSocket) 接口 +### 使用 http REST 接口 -| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -|------------------------|----------|------------|--------|--------|-------------|----------| -| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **批量拉取(基于 WebSocket)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **功能特性** | **Java** | **Python** | **Go** | **C#** | +| ------------ | -------- | ---------- | ------ | ------ | +| **连接管理** | 支持 | 支持 | 支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | 支持 | + +### 使用 Websocket 接口 + +| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +| ------------------- | -------- | ---------- | ------ | ------ | ----------- | -------- | +| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | :::warning - -- 参数绑定、数据订阅、Schemaless 和批量拉取功能仅在 WebSocket 连接下支持。 - 无论选用何种编程语言的连接器,2.0 及以上版本的 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池,以避免连接内的“USE statement”状态量在线程之间相互干扰(但连接的查询和写入操作都是线程安全的)。 ::: diff --git a/docs/zh/20-third-party/03-visual/01-grafana.mdx b/docs/zh/20-third-party/03-visual/01-grafana.mdx index 860087b901..93f0cf6eaa 100644 --- a/docs/zh/20-third-party/03-visual/01-grafana.mdx +++ b/docs/zh/20-third-party/03-visual/01-grafana.mdx @@ -7,13 +7,18 @@ toc_max_heading_level: 4 import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; -TDengine 能够与开源数据可视化系统 [Grafana](https://www.grafana.com/) 快速集成搭建数据监测报警系统,整个过程无需任何代码开发,TDengine 中数据表的内容可以在仪表盘(DashBoard)上进行可视化展现。关于 TDengine 插件的使用您可以在 [GitHub](https://github.com/taosdata/grafanaplugin/blob/master/README.md) 中了解更多。 +## 概述 +本文档介绍如何将 TDengine 数据源与开源数据可视化系统 [Grafana](https://www.grafana.com/) 集成,以实现数据的可视化和监测报警系统的搭建。通过 TDengine 插件,您可以轻松地将 TDengine 数据表的数据展示在 Grafana 仪表盘上,且无需进行复杂的开发工作。 + +## Grafana 版本要求 +当前 TDengine 支持 Grafana 7.5 及以上版本,建议使用最新版本。请根据您的系统环境下载并安装对应版本的 Grafana。 + ## 前置条件 要让 Grafana 能正常添加 TDengine 数据源,需要以下几方面的准备工作。 -- Grafana 服务已经部署并正常运行。目前 TDengine 支持 Grafana 7.5 以上的版本。用户可以根据当前的操作系统,到 Grafana 官网下载安装包,并执行安装。下载地址如下:[https://grafana.com/grafana/download](https://grafana.com/grafana/download) 。 +- Grafana 服务已经部署并正常运行。 :::info **注意**:要确保启动 Grafana 的账号有其安装目录的写权限,否则可能后面无法安装插件。 @@ -177,7 +182,15 @@ docker run -d \ ::: -## 内置变量和自定义变量 +## Dashboard 使用指南 + +本节内容按如下方式组织: +1. 介绍基础知识,包括 Grafana 的内置变量和自定义变量,TDengine 对与时序查询的特色语法支持。 +2. 介绍如何使用 TDengine 数据源在 Grafana 中创建 Dashboard,然后给出使用时序查询的特色语法和如何分组展示数据。 +3. 由于配置的 Dashbord 在页面显示时会定时查询 TDengine 来刷新显示,如果 SQL 编写不当会导致严重的性能问题,我们给出了性能优化建议。 +4. 最后我们以 TDengine 监控面板 TDinsight 为例介绍了如何导入我们提供的 DashBoard。 + +### Grafana 内置变量和自定义变量 Grafana 中的 Variable(变量)功能非常强大,可以在 Dashboard 的查询、面板标题、标签等地方使用,用来创建更加动态和交互式的 Dashbord,提高用户体验和效率。 @@ -191,7 +204,7 @@ Grafana 中的 Variable(变量)功能非常强大,可以在 Dashboard 的 Grafana 提供了内置变量和自定义变量,它们都可以可以在编写 SQL 时引用,引用的方式是 `$variableName`,`variableName` 是变量的名字,其他引用方式请参考 [引用方式](https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/)。 -### 内置变量 +#### 内置变量 Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana 插件面板。其含义如下: - `from` 查询范围的起始时间 @@ -202,13 +215,13 @@ Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana 除了上述三个常用变量,Grafana 还提供了如 `__timezone`, `__org`, `__user` 等变量,详情请参考 [内置变量](https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables)。 -### 自定义变量 +#### 自定义变量 我们可以在 Dashbord 中增加自定义变量。自定义变量和内置变量的使用方式没有区别,都是在 SQL 中用 `$variableName` 进行引用。 自定义变量支持多种类型,常见的类型包括 `Query`(查询)、`Constant`(常量)、`Interval`(间隔)、`Data source`(数据源)等。 自定义变量可以引用其他自定义变量,比如一个变量表示区域,另一个变量可以引用区域的值,来查询这个区域的设备。 -#### 添加查询类型变量 +##### 添加查询类型变量 在 Dashbord 的配置中,选择 【Variables】,然后点击 【New variable】: 1. 在 “Name” 字段中,输入你的变量名,此处我们设置变量名为 `selected_groups`。 @@ -221,7 +234,7 @@ Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana 我们还可以再新增自定义变量来引用这个 `selected_groups` 变量,比如我们新增一个名为 `tbname_max_current` 的查询变量,其 SQL 为 `select tbname from power.meters where groupid = $selected_groups and ts > $from and ts < $to;` -#### 添加间隔类型变量 +##### 添加间隔类型变量 我们可以自定义时间窗口间隔,可以更加贴合业务需求。 1. 在 “Name” 字段中,输入变量名为 `interval`。 @@ -237,7 +250,7 @@ Grafana 内置了 `from`、`to` 和 `interval` 等变量,都取自于 Grafana ::: -## TDengine 时间序列查询支持 +### TDengine 时序查询支持 TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序业务场景需求的特色查询语法,这些语法能够为时序场景的应用的开发带来极大的便利。 - `partition by` 子句可以按一定的维度对数据进行切分,然后在切分出的数据空间内再进行一系列的计算。绝大多数情况可以替代 `group by`。 @@ -247,15 +260,16 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 上述特性详细介绍可以参考 [特色查询](../../../reference/taos-sql/distinguished/)。 -## 创建 Dashboard +### 创建 Dashboard -回到主界面创建 Dashboard,点击【Add Query】进入面板查询页面: +有了前面的基础知识,我们可以配置基于 TDengine 数据源的时间序列数据展示 Dashbord。 +在 Grafana 主界面创建 Dashboard,点击【Add Query】进入面板查询页面: ![TDengine Database Grafana plugin create dashboard](./create_dashboard1.webp) 如上图所示,在 “Query” 中选中 `TDengine` 数据源,在下方查询框可输入相应 SQL 进行查询。 我们继续用智能电表来举例,为了展示曲线美观,此处**用了虚拟数据**。 -## 时间序列数据展示 +#### 时间序列数据展示 假设我们想查询一段时间内的平均电流大小,时间窗口按 `$interval` 切分,若某一时间窗口区间数据缺失,填充 null。 - “INPUT SQL”:输入要查询的语句(该 SQL 语句的结果集应为两列多行),此处输入:`select _wstart as ts, avg(current) as current from power.meters where groupid in ($selected_groups) and ts > $from and ts < $to interval($interval) fill(null)` ,其中,from、to 和 interval 为 Grafana 内置变量,selected_groups 为自定义变量。 @@ -272,7 +286,7 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 ::: -## 时间序列数据分组展示 +#### 时间序列数据分组展示 假设我们想查询一段时间内的平均电流大小,按 `groupid` 分组展示,我们可以修改之前的 SQL 为 `select _wstart as ts, groupid, avg(current) as current from power.meters where ts > $from and ts < $to partition by groupid interval($interval) fill(null)` @@ -285,12 +299,12 @@ TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序 > 关于如何使用 Grafana 创建相应的监测界面以及更多有关使用 Grafana 的信息,请参考 Grafana 官方的[文档](https://grafana.com/docs/)。 -## 性能建议 +### 性能优化建议 - **所有查询加上时间范围**,在时序数据库中,如果不加查询的时间范围,会扫表导致性能低下。常见的 SQL 写法是 `select column_name from db.table where ts > $from and ts < $to;` - 对于最新状态类型的查询,我们一般建议在**创建数据库的时候打开缓存**(`CACHEMODEL` 设置为 last_row 或者 both),常见的 SQL 写法是 `select last(column_name) from db.table where ts > $from and ts < $to;` -## 导入 Dashboard +### 导入 Dashboard 在数据源配置页面,您可以为该数据源导入 TDinsight 面板,作为 TDengine 集群的监控可视化工具。如果 TDengine 服务端为 3.0 版本请选择 `TDinsight for 3.x` 导入。注意 TDinsight for 3.x 需要运行和配置 taoskeeper。 @@ -317,7 +331,7 @@ TDengine Grafana 插件支持告警,如果要配置告警,需要以下几个 3.4 配置标签和告警通道 3.5 配置通知文案 -### 告警配置界面 +### 告警配置界面介绍 在Grafana 11 告警界面一共有 6 个 Tab,分别是 “Alert rules”、“Contact points”、“Notification policies”、“Silences”、 “Groups” 和 “Settings”。 - “Alert rules” 告警规则列表,用于展示和配置告警规则 @@ -329,7 +343,7 @@ TDengine Grafana 插件支持告警,如果要配置告警,需要以下几个 ### 配置联络点 -以邮件和飞书为例配置联络点。 +本节以邮件和飞书为例配置联络点。 #### 配置邮件联络点 diff --git a/examples/JDBC/connectionPools/pom.xml b/examples/JDBC/connectionPools/pom.xml index 61717cf112..855d531f4c 100644 --- a/examples/JDBC/connectionPools/pom.xml +++ b/examples/JDBC/connectionPools/pom.xml @@ -18,7 +18,7 @@ com.taosdata.jdbc taos-jdbcdriver - 3.0.0 + 3.3.0 diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/DruidDemo.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/DruidDemo.java index c7df4e0dec..dd96f5c632 100644 --- a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/DruidDemo.java +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/DruidDemo.java @@ -22,7 +22,7 @@ public static void main(String[] args) throws Exception { dataSource.setMinIdle(10); dataSource.setMaxActive(10); dataSource.setMaxWait(30000); - dataSource.setValidationQuery("SELECT SERVER_STATUS()"); + dataSource.setValidationQuery("SELECT SERVER_VERSION()"); Connection connection = dataSource.getConnection(); // get connection Statement statement = connection.createStatement(); // get statement diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java index 500f0e9e97..a4581ac4b6 100644 --- a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java @@ -20,7 +20,7 @@ public class DruidPoolBuilder { dataSource.setMinIdle(poolSize); dataSource.setMaxActive(poolSize); dataSource.setMaxWait(30000); - dataSource.setValidationQuery("select server_status()"); + dataSource.setValidationQuery("select SERVER_VERSION()"); return dataSource; } diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java index 7e151de3e0..ffd43cc3ea 100644 --- a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java @@ -20,7 +20,7 @@ public class HikariCpBuilder { config.setConnectionTimeout(30000); //maximum wait milliseconds for get connection from pool config.setMaxLifetime(0); // maximum life time for each connection config.setIdleTimeout(0); // max idle time for recycle idle connection - config.setConnectionTestQuery("select server_status()"); //validation query + config.setConnectionTestQuery("select SERVER_VERSION()"); //validation query HikariDataSource ds = new HikariDataSource(config); return ds; diff --git a/examples/JDBC/connectionPools/src/main/resources/proxool.xml b/examples/JDBC/connectionPools/src/main/resources/proxool.xml index 67baa1c393..0e2ac6368a 100644 --- a/examples/JDBC/connectionPools/src/main/resources/proxool.xml +++ b/examples/JDBC/connectionPools/src/main/resources/proxool.xml @@ -22,6 +22,6 @@ 30000 - select server_status() + select server_version() \ No newline at end of file From 8b8e217130e545aa31029419431b98956fac3143 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 9 Aug 2024 19:14:13 +0800 Subject: [PATCH 27/34] doc: update udf --- docs/zh/08-develop/09-udf.md | 54 +++++++++++++++--------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md index bc62dbfa3c..b16700b460 100644 --- a/docs/zh/08-develop/09-udf.md +++ b/docs/zh/08-develop/09-udf.md @@ -429,7 +429,9 @@ def process(block): 这个文件包含 3 个函数, init 和 destroy 都是空函数,它们是 UDF 的生命周期函数,即使什么都不做也要定义。最关键的是 process 函数, 它接受一个数据块,这个数据块对象有两个方法。 1. shape() 返回数据块的行数和列数 2. data(i, j) 返回 i 行 j 列的数据 -标量函数的 process 方法传入的数据块有多少行,就需要返回多少行数据。上述代码忽略列数,因为只需对每行的第一个数做计算。 + +标量函数的 process 方法传入的数据块有多少行,就需要返回多少行数据。上述代码忽略列数,因为只需对每行的第一列做计算。 + 接下来创建对应的 UDF 函数,在 TDengine CLI 中执行下面语句。 ```sql @@ -442,7 +444,7 @@ taos> create function myfun as '/root/udf/myfun.py' outputtype double language ' Create OK, 0 row(s) affected (0.005202s) ``` -看起来很顺利,接下来 show 一下系统中所有的自定义函数,确认创建成功。 +看起来很顺利,接下来查看系统中所有的自定义函数,确认创建成功。 ```text taos> show functions; @@ -452,7 +454,7 @@ taos> show functions; Query OK, 1 row(s) in set (0.005767s) ``` -接下来就来测试一下这个函数,测试之前先执行下面的 SQL 命令,制造些测试数据,在 TDengine CLI 中执行下述命令。 +生成测试数据,可以在 TDengine CLI 中执行下述命令。 ```sql create database test; @@ -470,8 +472,7 @@ taos> select myfun(v1, v2) from t; DB error: udf function execution failure (0.011088s) ``` -不幸的是执行失败了,什么原因呢? -查看 udfd 进程的日志。 +不幸的是执行失败了,什么原因呢?查看 udfd 进程的日志。 ```shell tail -10 /var/log/taos/udfd.log @@ -514,8 +515,7 @@ taos> select myfun(v1, v2) from t; 2.302585093 | ``` -2. 没有处理 null 值。我们期望如果输入有 null,则会抛异常终止执行。 -因此 process 函数改进如下。 +2. 没有处理 null 值。我们期望如果输入有 null,则会抛异常终止执行。因此 process 函数改进如下。 ```python def process(block): @@ -525,7 +525,7 @@ def process(block): return [ None if block.data(i, 0) is None else log(block.data(i, 0) ** 2 + 1) for i in range(rows)] ``` -然后执行下面的语句更新已有的 UDF。 +执行如下语句更新已有的 UDF。 ```sql create or replace function myfun as '/root/udf/myfun.py' outputtype double language 'Python'; @@ -539,7 +539,7 @@ taos> select myfun(v1, v2) from t; DB error: udf function execution failure (0.014643s) ``` -但遗憾的是我们自定义的异常信息没有展示给用户,而是在插件的日志文件 /var/log/taos/taospyudf.log 中。 +自定义的异常信息打印在插件的日志文件 /var/log/taos/taospyudf.log 中。 ```text 2023-05-24 23:21:06.790 ERROR [1666188] [doPyUdfScalarProc@507] call pyUdfScalar proc function. context 0x7faade26d180. error: Exception: require 1 parameter but given 2 @@ -554,18 +554,17 @@ At: #### 示例三 -编写一个 UDF:输入(x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和: 1 * x1 + 2 * x2 + ... + n * xn。如果 x1 至 xn 中包含 null,则结果为 null。 -这个示例与示例一的区别是,可以接受任意多列作为输入,且要处理每一列的值。编写 UDF 文件 /root/udf/nsum.py。 +输入(x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和:1 * x1 + 2 * x2 + ... + n * xn。如果 x1 至 xn 中包含 null,则结果为 null。 + +本例与示例一的区别是,可以接受任意多列作为输入,且要处理每一列的值。编写 UDF 文件 /root/udf/nsum.py。 ```python def init(): pass - def destroy(): pass - def process(block): rows, cols = block.shape() result = [] @@ -617,11 +616,9 @@ pip3 install moment ```python import moment - def init(): pass - def destroy(): pass @@ -651,7 +648,7 @@ DB error: udf function execution failure (1.123615s) ``` ```shell - tail -20 taospyudf.log +tail -20 taospyudf.log 2023-05-25 11:42:34.541 ERROR [1679419] [PyUdf::PyUdf@217] py udf load module failure. error ModuleNotFoundError: No module named 'moment' ``` @@ -707,26 +704,21 @@ import pickle LOG_FILE: io.TextIOBase = None - def init(): global LOG_FILE LOG_FILE = open("/var/log/taos/spread.log", "wt") log("init function myspead success") - def log(o): LOG_FILE.write(str(o) + '\n') - def destroy(): log("close log file: spread.log") LOG_FILE.close() - def start(): return pickle.dumps((-math.inf, math.inf)) - def reduce(block, buf): max_number, min_number = pickle.loads(buf) log(f"initial max_number={max_number}, min_number={min_number}") @@ -741,20 +733,20 @@ def reduce(block, buf): min_number = v return pickle.dumps((max_number, min_number)) - def finish(buf): max_number, min_number = pickle.loads(buf) return max_number - min_number ``` -在这个示例中我们不光定义了一个聚合函数,还添加记录执行日志的功能,讲解如下。 -1. init 函数不再是空函数,而是打开了一个文件用于写执行日志 -2. log 函数是记录日志的工具,自动将传入的对象转成字符串,加换行符输出 -3. destroy 函数用来在执行结束关闭文件 -4. start 返回了初始的 buffer,用来存聚合函数的中间结果,我们把最大值初始化为负无穷大,最小值初始化为正无穷大 -5. reduce 处理每个数据块并聚合结果 -6. finish 函数将最终的 buffer 转换成最终的输出 -执行下面的 SQL语句创建对应的 UDF。 +在这个示例中,我们不但定义了一个聚合函数,还增加了记录执行日志的功能。 +1. init 函数打开一个文件用于记录日志 +2. log 函数记录日志,自动将传入的对象转成字符串,加换行符输出 +3. destroy 函数在执行结束后关闭日志文件 +4. start 函数返回初始的 buffer,用来存聚合函数的中间结果,把最大值初始化为负无穷大,最小值初始化为正无穷大 +5. reduce 函数处理每个数据块并聚合结果 +6. finish 函数将 buffer 转换成最终的输出 + +执行下面 SQL 语句创建对应的 UDF。 ```sql create or replace aggregate function myspread as '/root/udf/myspread.py' outputtype double bufsize 128 language 'Python'; @@ -785,7 +777,7 @@ taos> select spread(v1) from t; Query OK, 1 row(s) in set (0.005501s) ``` -最后,查看我们自己打印的执行日志,从日志可以看出,reduce 函数被执行了 3 次。执行过程中 max 值被更新了 4 次, min 值只被更新 1 次。 +最后,查看执行日志,可以看到 reduce 函数被执行了 3 次,执行过程中 max 值被更新了 4 次,min 值只被更新 1 次。 ```shell root@slave11 /var/log/taos $ cat spread.log From 809d54599f4311a1e8ddf80f2580fe8bb74a75dd Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 9 Aug 2024 19:27:28 +0800 Subject: [PATCH 28/34] doc: minor changes --- docs/zh/08-develop/09-udf.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md index b16700b460..fab59cc2eb 100644 --- a/docs/zh/08-develop/09-udf.md +++ b/docs/zh/08-develop/09-udf.md @@ -846,7 +846,7 @@ pycumsum 使用 numpy 计算输入列所有数据的累积和。 创建标量函数的 SQL 语法如下。 ```sql -CREATE OR REPLACE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python'; +CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python'; ``` 各参数说明如下。 - or replace:如果函数已经存在,则会修改已有的函数属性。 @@ -859,8 +859,9 @@ CREATE OR REPLACE FUNCTION function_name AS library_path OUTPUTTYPE output_type ### 创建聚合函数 创建聚合函数的 SQL 语法如下。 + ```sql -CREATE OR REPLACE AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type LANGUAGE 'Python'; +CREATE [OR REPLACE] AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type BUFSIZE 其中,buffer_size LANGUAGE 'Python'; ``` 其中,buffer_size 表示中间计算结果的缓冲区大小,单位是字节。其他参数的含义与标量函数相同。 @@ -872,7 +873,7 @@ CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUT ### 删除 UDF -删除指定名称的 UDF 的 SQL 语法如下: +删除指定名称的 UDF 的 SQL 语法如下。 ```sql DROP FUNCTION function_name; ``` From 3300877339e2ad9b28e5426cefab8881b343c465 Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Fri, 9 Aug 2024 19:28:18 +0800 Subject: [PATCH 29/34] improve tdinsight doc --- .../01-components/12-tdinsight/index.mdx | 72 +------------------ 1 file changed, 2 insertions(+), 70 deletions(-) diff --git a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx index 34a06e13c4..e5f44a1080 100644 --- a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx +++ b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx @@ -32,76 +32,8 @@ TDengine 通过 taosKeeper 将服务器的 CPU、内存、硬盘空间、带宽 -## 安装 TDengine 数据源插件 - -TDengine 数据源插件支持图形界面安装、手动安装和脚本安装三种安装方式,一般建议图形界面安装。对于 Grafana 8.5 以下版本可以使用手动安装和脚本安装方式。 - - - - -使用 Grafana 最新版本(8.5+),您可以在 Grafana 中[浏览和管理插件](https://grafana.com/docs/grafana/next/administration/plugin-management/#plugin-catalog)。在 Grafana 管理界面中的 **Configurations > Plugins** 页面直接搜索 `TDengine` 并按照提示安装。 - - - - -从 GitHub 安装 TDengine 最新版数据源插件。 - -```bash -get_latest_release() { - curl --silent "https://api.github.com/repos/taosdata/grafanaplugin/releases/latest" | - grep '"tag_name":' | - sed -E 's/.*"v([^"]+)".*/\1/' -} -TDENGINE_PLUGIN_VERSION=$(get_latest_release) -sudo grafana-cli \ - --pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v$TDENGINE_PLUGIN_VERSION/tdengine-datasource-$TDENGINE_PLUGIN_VERSION.zip \ - plugins install tdengine-datasource -``` - -:::note -3.1.6 和更早版本插件需要在配置文件 `/etc/grafana/grafana.ini` 中添加如下设置,以启用未签名插件。 - -```ini -[plugins] -allow_loading_unsigned_plugins = tdengine-datasource -``` - -::: - - - - - -我们提供了一个自动化安装脚本 [TDinsight.sh](https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh) 脚本以便用户快速进行安装配置。 - -您可以通过 `wget` 或其他工具下载该脚本: - -```bash -wget https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh -chmod +x TDinsight.sh -./TDinsight.sh -``` - -这个脚本会自动下载最新的[Grafana TDengine 数据源插件](https://github.com/taosdata/grafanaplugin/releases/latest) 和 [TDinsight 仪表盘](https://github.com/taosdata/grafanaplugin/blob/master/dashboards/TDinsightV3.json) ,将命令行选项中的可配置参数转为 [Grafana Provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/) 配置文件,以进行自动化部署及更新等操作。 - -1. 假设您在同一台主机上使用 TDengine 和 Grafana 服务。 运行 `./TDinsight.sh` 并打开 Grafana 页面就可以看到 TDinsight 仪表盘了。 -2. 假设您在主机 `tdengine` 上启动 TDengine 数据库,taosAdapter 的 HTTP 监听端口为 `6041`,用户为 `root1`,密码为 `pass5ord`。执行脚本:`./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord` - -详细的使用方法请参考 [TDinsight.sh 详细说明](./#附录) - - - - - -## 添加 TDengine 数据源 - -安装完毕后, 点击 “Connections” -> “Data sources“, 然后选择 ”tdengine-datasource“,输入 TDengine 相关配置: -- Host: TDengine 集群中提供 REST 服务的 IP 地址与端口号,默认 `http://localhost:6041` -- User:TDengine 用户名。 -- Password:TDengine 用户密码。 - -点击 `Save & Test` 进行测试,成功会提示:`TDengine Data source is working`。 - +## 安装 TDengine 数据源插件和配置数据源 +安装 Grafana TDengine 数据源插件和配置数据源的步骤请参考:[与 Grafana 集成](../../../third-party/visual/grafana/#安装-grafana-plugin-并配置数据源) ## 导入 TDinsightV3 仪表盘 From fc90d17248bba050e98f0d9b0d7590ee40a7f807 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 9 Aug 2024 19:37:39 +0800 Subject: [PATCH 30/34] docs: minor changes --- docs/zh/08-develop/09-udf.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md index fab59cc2eb..72291b65e6 100644 --- a/docs/zh/08-develop/09-udf.md +++ b/docs/zh/08-develop/09-udf.md @@ -861,7 +861,7 @@ CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_typ 创建聚合函数的 SQL 语法如下。 ```sql -CREATE [OR REPLACE] AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type BUFSIZE 其中,buffer_size LANGUAGE 'Python'; +CREATE [OR REPLACE] AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type BUFSIZE buffer_size LANGUAGE 'Python'; ``` 其中,buffer_size 表示中间计算结果的缓冲区大小,单位是字节。其他参数的含义与标量函数相同。 From 2f1f8605d9ed7d50f1acf0310d66bc6aff40ee93 Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Sat, 10 Aug 2024 10:39:22 +0800 Subject: [PATCH 31/34] mod validation sql in jdbc demo properties --- examples/JDBC/springbootdemo/readme.md | 2 +- .../springbootdemo/src/main/resources/application.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/JDBC/springbootdemo/readme.md b/examples/JDBC/springbootdemo/readme.md index a89e21c009..625d43e4ed 100644 --- a/examples/JDBC/springbootdemo/readme.md +++ b/examples/JDBC/springbootdemo/readme.md @@ -22,7 +22,7 @@ spring.datasource.druid.max-active=5 # max wait time for get connection, ms spring.datasource.druid.max-wait=60000 -spring.datasource.druid.validation-query=select server_status(); +spring.datasource.druid.validation-query=select SERVER_VERSION(); spring.datasource.druid.validation-query-timeout=5000 spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false diff --git a/examples/JDBC/springbootdemo/src/main/resources/application.properties b/examples/JDBC/springbootdemo/src/main/resources/application.properties index c523952fb6..00a06a5098 100644 --- a/examples/JDBC/springbootdemo/src/main/resources/application.properties +++ b/examples/JDBC/springbootdemo/src/main/resources/application.properties @@ -12,7 +12,7 @@ spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=5 spring.datasource.druid.max-wait=30000 -spring.datasource.druid.validation-query=select server_status(); +spring.datasource.druid.validation-query=select SERVER_VERSION(); spring.aop.auto=true spring.aop.proxy-target-class=true #mybatis From 0ea143d319c03c7db57f52eab84f78ae3c349024 Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Sat, 10 Aug 2024 11:47:13 +0800 Subject: [PATCH 32/34] improve Preconditions --- docs/zh/07-operation/05-monitor.md | 33 ++++++++++++++---------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/docs/zh/07-operation/05-monitor.md b/docs/zh/07-operation/05-monitor.md index cd8a9772cd..abbd54736b 100644 --- a/docs/zh/07-operation/05-monitor.md +++ b/docs/zh/07-operation/05-monitor.md @@ -40,21 +40,21 @@ taosKeeper 的配置文件默认位于 `/etc/taos/taoskeeper.toml`。 详细配 #### 导入仪表盘 -TDengine 数据源插件已被提交至 Grafana 官网,完成插件的安装和数据源的创建后,可以进行 TDinsight 仪表盘的导入。 +TDengine 数据源插件已提交至 Grafana 官网,如何安装 TDengine 数据源插件和配置数据源请参考:[安装 Grafana Plugin 并配置数据源](../../third-party/visual/grafana/#安装-grafana-plugin-并配置数据源)。完成插件的安装和数据源的创建后,可以进行 TDinsight 仪表盘的导入。 -在 Grafana 的 ”Home“ -> ”Dashboards“ 页面,点击位于右上角的 ”New“ -> ”import“ 按钮,即可进入 Dashboard 的导入页面,它支持以下两种导入方式。 +在 Grafana 的 “Home” -> “Dashboards” 页面,点击位于右上角的 “New” -> “import” 按钮,即可进入 Dashboard 的导入页面,它支持以下两种导入方式。 - Dashboard ID:18180。 - Dashboard URL:https://grafana.com/grafana/dashboards/18180-tdinsight-for-3-x/ -填写以上 Dashboard ID 或 Dashboard URL 以后,点击 ”Load“ 按钮,按照向导操作,即可完成导入。导入成功后,Dashboards 列表页面会出现 ”TDinsight for 3.x“ 仪表盘,点击进入后,就可以看到 TDinsight 中已创建的各个指标的面板,如下图所示: +填写以上 Dashboard ID 或 Dashboard URL 以后,点击 “Load” 按钮,按照向导操作,即可完成导入。导入成功后,Dashboards 列表页面会出现 “TDinsight for 3.x” 仪表盘,点击进入后,就可以看到 TDinsight 中已创建的各个指标的面板,如下图所示: ![TDinsight 界面示例](./TDinsight-1-cluster-status.webp) -**注意** 在 TDinsight 界面左上角的 ”Log from“ 下拉列表中可以选择 `log` 数据库。 +**注意** 在 TDinsight 界面左上角的 “Log from” 下拉列表中可以选择 `log` 数据库。 ### TDengine V3 监控数据 -TDinsight dashboard 数据来源于 `log` 库(存放监控数据的默认数据库,可以在 taoskeeper 配置文件中修改)。”TDinsight for 3.x“ 仪表盘查询了 taosd 和 TaosAdapter 的监控指标。 +TDinsight dashboard 数据来源于 `log` 库(存放监控数据的默认数据库,可以在 taoskeeper 配置文件中修改)。“TDinsight for 3.x” 仪表盘查询了 taosd 和 TaosAdapter 的监控指标。 - taosd 的监控指标请参考 [taosd 监控指标](../../reference/components/taosd/#taosd-监控指标) - taosAdapter 的监控指标请参考 [taosAdapter 监控指标](../../reference/components/taosadapter/#taosadapter-监控指标) @@ -66,18 +66,15 @@ taosX 是 TDengine 中提供零代码数据接入能力的核心组件,对它 3. 运行在 taosX 端或 taosx-agent 端的各个连接器子进程 4. 运行中的各类数据写入任务 -### 版本支持 +### 前置条件 -1. TDengine 企业版本 3.2.3.0 或以上版本包含的 taosX 才包含此功能。如果单独安装 taosX,需要 taosX 1.5.0 或以上版本。 -2. 需要安装 Grafana 插件 [TDengie Datasource v3.5.0](https://grafana.com/grafana/plugins/tdengine-datasource/) 或以上版本。 +1. taosd,taosAdapter 和 taosKeeper 都已经部署完成并启动成功。 +2. taosX 服务监控配置正确,如何配置可以参考下文 “配置 taosX 监控”,服务启动成功。 + **注意**:TDengine 企业版本 3.2.3.0 或以上版本包含的 taosX 才包含此功能。如果单独安装 taosX,需要 taosX 1.5.0 或以上版本。 +3. 部署 Grafana ,安装 TDengine Datasource 插件,配置好数据源。可以参考:[安装 Grafana Plugin 并配置数据源](../../third-party/visual/grafana/#安装-grafana-plugin-并配置数据源)。 + **注意**:需要安装 Grafana 插件 [TDengie Datasource v3.5.0](https://grafana.com/grafana/plugins/tdengine-datasource/) 或以上版本。 -### 准备工作 - -假设你已经部署好了 taosd,taosAdapter 和 taosAdapter。 那么还需要: -1. 启动 taosX 服务。 -2. 部署 Grafana ,安装 TDengine Datasource 插件,配置好数据源。 - -### 配置 taosX +### 配置 taosX 监控 toasX 的配置文件(默认 /etc/taos/taosx.toml) 中与 monitor 相关的配置如下: @@ -101,12 +98,12 @@ toasX 的配置文件(默认 /etc/taos/taosx.toml) 中与 monitor 相关的配 ### 基于 TDinsight 监控 tasoX -"TDinsight for taosX" 是专门为 taosX 监控创建的 Grafana 面板。使用前需要先导入这个面板。 +“TDinsight for taosX” 是专门为 taosX 监控创建的 Grafana 面板。使用前需要先导入这个面板。 #### 进入面板 -1. 在 Grafana 界面菜单中点击 ”Data sources“, 然后选择已经配置好的 TDengine 数据源。 -2. 在数据源配置界面选择 “Dashboard” Tab, 然后导入 ”TDinsight for taosX“ 面板(第一次使用需要先导入)。 下面是一个示例图: +1. 在 Grafana 界面菜单中点击 “Data sources”, 然后选择已经配置好的 TDengine 数据源。 +2. 在数据源配置界面选择 “Dashboard” Tab, 然后导入 “TDinsight for taosX” 面板(第一次使用需要先导入)。 下面是一个示例图: ![monitor rows](./pic/monitor-04.jpg) From f09ddfa815ce63e834a2149098f35c95781c8c2c Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Sat, 10 Aug 2024 16:47:56 +0800 Subject: [PATCH 33/34] improve a note in grafana doc --- docs/zh/20-third-party/03-visual/01-grafana.mdx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/zh/20-third-party/03-visual/01-grafana.mdx b/docs/zh/20-third-party/03-visual/01-grafana.mdx index 93f0cf6eaa..d7406352c9 100644 --- a/docs/zh/20-third-party/03-visual/01-grafana.mdx +++ b/docs/zh/20-third-party/03-visual/01-grafana.mdx @@ -18,12 +18,8 @@ import TabItem from "@theme/TabItem"; 要让 Grafana 能正常添加 TDengine 数据源,需要以下几方面的准备工作。 -- Grafana 服务已经部署并正常运行。 - :::info - +- Grafana 服务已经部署并正常运行。 **注意**:要确保启动 Grafana 的账号有其安装目录的写权限,否则可能后面无法安装插件。 - - ::: - TDengine 集群已经部署并正常运行。 - taosAdapter 已经安装并正常运行。具体细节请参考 [taosAdapter 的使用手册](../../../reference/components/taosadapter) From c1727ef2aeaeebca96596676fc8ffc3040ef31dc Mon Sep 17 00:00:00 2001 From: sheyanjie-qq <249478495@qq.com> Date: Mon, 12 Aug 2024 08:50:31 +0800 Subject: [PATCH 34/34] add tab for not support language --- .../03-insert-data/01-sql-writing.mdx | 4 +- .../03-insert-data/30-influxdb-line.mdx | 2 +- .../03-insert-data/40-opentsdb-telnet.mdx | 2 +- .../03-insert-data/50-opentsdb-json.mdx | 2 +- docs/en/07-develop/04-query-data/index.mdx | 2 +- docs/zh/08-develop/01-connect/index.md | 42 ++++++++- docs/zh/08-develop/02-sql.md | 8 +- docs/zh/08-develop/04-schemaless.md | 16 +++- docs/zh/08-develop/05-stmt.md | 13 ++- docs/zh/08-develop/07-tmq.md | 86 ++++++++++++++++--- docs/zh/14-reference/05-connector/index.md | 18 ++-- 11 files changed, 159 insertions(+), 36 deletions(-) diff --git a/docs/en/07-develop/03-insert-data/01-sql-writing.mdx b/docs/en/07-develop/03-insert-data/01-sql-writing.mdx index b9ec36e3ac..8f7e573995 100644 --- a/docs/en/07-develop/03-insert-data/01-sql-writing.mdx +++ b/docs/en/07-develop/03-insert-data/01-sql-writing.mdx @@ -88,7 +88,7 @@ For more details about `INSERT` please refer to [INSERT](../../../taos-sql/inser - + @@ -128,7 +128,7 @@ Parameter binding is available only with native connection. - + diff --git a/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx b/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx index ddcaad8914..abba88e70f 100644 --- a/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx +++ b/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx @@ -60,7 +60,7 @@ For more details please refer to [InfluxDB Line Protocol](https://docs.influxdat - + diff --git a/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx b/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx index ed2659042f..0a79823d0e 100644 --- a/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx +++ b/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx @@ -52,7 +52,7 @@ meters.current 1648432611250 11.3 location=California.LosAngeles groupid=3 - + diff --git a/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx b/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx index fc54421daf..39004be254 100644 --- a/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx +++ b/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx @@ -67,7 +67,7 @@ Please refer to [OpenTSDB HTTP API](http://opentsdb.net/docs/build/html/api_http - + diff --git a/docs/en/07-develop/04-query-data/index.mdx b/docs/en/07-develop/04-query-data/index.mdx index 8e21fd325c..164ec0d0a6 100644 --- a/docs/en/07-develop/04-query-data/index.mdx +++ b/docs/en/07-develop/04-query-data/index.mdx @@ -142,7 +142,7 @@ In the section describing [Insert](../insert-data/sql-writing), a database named - + diff --git a/docs/zh/08-develop/01-connect/index.md b/docs/zh/08-develop/01-connect/index.md index fdde4aea2e..755a9e7f74 100644 --- a/docs/zh/08-develop/01-connect/index.md +++ b/docs/zh/08-develop/01-connect/index.md @@ -20,7 +20,7 @@ import VerifyLinux from "../../14-reference/05-connector/_verify_linux.mdx"; import VerifyMacOS from "../../14-reference/05-connector/_verify_macos.mdx"; import VerifyWindows from "../../14-reference/05-connector/_verify_windows.mdx"; -TDengine 提供了丰富的应用程序开发接口,为了便于用户快速开发自己的应用,TDengine 支持了多种编程语言的连接器,其中官方连接器包括支持 C/C++、Java、Python、Go、Node.js、C#、Rust、Lua(社区贡献)和 PHP (社区贡献)的连接器。这些连接器支持使用原生接口(taosc)和 REST 接口(部分语言暂不支持)连接 TDengine 集群。社区开发者也贡献了多个非官方连接器,例如 ADO.NET 连接器、Lua 连接器和 PHP 连接器。 +TDengine 提供了丰富的应用程序开发接口,为了便于用户快速开发自己的应用,TDengine 支持了多种编程语言的连接器,其中官方连接器包括支持 C/C++、Java、Python、Go、Node.js、C#、Rust、Lua(社区贡献)和 PHP (社区贡献)的连接器。这些连接器支持使用原生接口(taosc)和 REST 接口(部分语言暂不支持)连接 TDengine 集群。社区开发者也贡献了多个非官方连接器,例如 ADO.NET 连接器、Lua 连接器和 PHP 连接器。另外 TDengine 还可以直接调用 taosadapter 提供的 REST API 接口,进行数据写入和查询操作。 ## 连接方式 @@ -33,6 +33,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 ![TDengine connection type](connection-type-zh.webp) 无论使用何种方式建立连接,连接器都提供了相同或相似的 API 操作数据库,都可以执行 SQL 语句,只是初始化连接的方式稍有不同,用户在使用上不会感到什么差别。 +各种连接方式和各语言连接器支持情况请参考:[连接器功能特性](../../reference/connector/#功能特性) 关键不同点在于: @@ -251,7 +252,10 @@ dotnet add package TDengine.Connector 如果已经安装了 TDengine 服务端软件或 TDengine 客户端驱动 taosc, 那么已经安装了 C 连接器,无需额外操作。 -
+ +
+ +使用 REST API 方式访问 TDengine,无需安装任何驱动和连接器。 @@ -394,7 +398,10 @@ C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数 还提供了 `taos_connect_auth()` 函数用于使用 MD5 加密的密码建立与 TDengine 数据库的连接。此函数与 `taos_connect` 功能相同,不同之处在于密码的处理方式,`taos_connect_auth` 需要的是密码的 MD5 加密字符串。
+ +使用 REST API 方式访问 TDengine,由应用程序去建立 HTTP 连接,自己控制 HTTP 连接参数。 + ### Websocket 连接 @@ -431,6 +438,13 @@ C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数 {{#include docs/examples/csharp/wsConnect/Program.cs:main}} ```
+ +不支持 + + +不支持 + + ### 原生连接 @@ -455,6 +469,9 @@ C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数 {{#include docs/examples/rust/nativeexample/examples/connect.rs}} ```
+ +不支持 + ```csharp {{#include docs/examples/csharp/connect/Program.cs:main}} @@ -464,6 +481,10 @@ C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数 + +不支持 + + ### REST 连接 @@ -485,6 +506,23 @@ C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数 {{#include docs/examples/go/connect/restexample/main.go}} ```
+ +不支持 + + +不支持 + + +不支持 + + +不支持 + + + +使用 REST API 方式访问 TDengine,由应用程序自主去建立 HTTP 连接。 + + diff --git a/docs/zh/08-develop/02-sql.md b/docs/zh/08-develop/02-sql.md index 3cad007078..1651bf21cd 100644 --- a/docs/zh/08-develop/02-sql.md +++ b/docs/zh/08-develop/02-sql.md @@ -57,7 +57,7 @@ REST API:直接调用 `taosadapter` 提供的 REST API 接口,进行数据 ```
- + ```js {{#include docs/examples/node/websocketexample/sql_example.js:create_db_and_table}} ``` @@ -133,7 +133,7 @@ NOW 为系统内部函数,默认为客户端所在计算机当前时间。 NOW ``` - + ```js {{#include docs/examples/node/websocketexample/sql_example.js:insertData}} ``` @@ -207,7 +207,7 @@ rust 连接器还支持使用 **serde** 进行反序列化行为结构体的结 ``` - + ```js {{#include docs/examples/node/websocketexample/sql_example.js:queryData}} ``` @@ -282,7 +282,7 @@ reqId 可用于请求链路追踪,reqId 就像分布式系统中的 traceId ``` - + ```js {{#include docs/examples/node/websocketexample/sql_example.js:sqlWithReqid}} ``` diff --git a/docs/zh/08-develop/04-schemaless.md b/docs/zh/08-develop/04-schemaless.md index 1bc750c3cb..06dec726e9 100644 --- a/docs/zh/08-develop/04-schemaless.md +++ b/docs/zh/08-develop/04-schemaless.md @@ -194,7 +194,7 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO ``` - + ```js {{#include docs/examples/node/websocketexample/line_example.js}} ``` @@ -204,6 +204,12 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO {{#include docs/examples/csharp/wssml/Program.cs:main}} ``` + +不支持 + + +不支持 + ### 原生连接 @@ -237,7 +243,9 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO {{#include docs/examples/rust/nativeexample/examples/schemaless.rs}} ``` - + + +不支持 ```csharp @@ -249,7 +257,9 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO {{#include docs/examples/c/sml_insert_demo.c:schemaless}} ``` - + +不支持 + ## 查询写入的数据 diff --git a/docs/zh/08-develop/05-stmt.md b/docs/zh/08-develop/05-stmt.md index 0e94af4a34..4b8dbbce9b 100644 --- a/docs/zh/08-develop/05-stmt.md +++ b/docs/zh/08-develop/05-stmt.md @@ -63,6 +63,12 @@ import TabItem from "@theme/TabItem"; {{#include docs/examples/csharp/wsStmt/Program.cs:main}} ``` + +不支持 + + +不支持 + ## 原生连接 @@ -93,6 +99,9 @@ import TabItem from "@theme/TabItem"; {{#include docs/examples/rust/nativeexample/examples/stmt.rs}} ``` + + +不支持 ```csharp @@ -104,5 +113,7 @@ import TabItem from "@theme/TabItem"; {{#include docs/examples/c/stmt_insert_demo.c}} ``` - + +不支持 + diff --git a/docs/zh/08-develop/07-tmq.md b/docs/zh/08-develop/07-tmq.md index 3ee606741c..0711ab9f28 100644 --- a/docs/zh/08-develop/07-tmq.md +++ b/docs/zh/08-develop/07-tmq.md @@ -96,6 +96,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 同通用基础配置项。 + +不支持 + ### Websocket 连接 @@ -148,6 +151,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 {{#include docs/examples/csharp/wssubscribe/Program.cs:create_consumer}} ``` + +不支持 + + +不支持 + @@ -187,7 +196,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 ```
- + +不支持 + ```csharp {{#include docs/examples/csharp/subscribe/Program.cs:create_consumer}} @@ -206,7 +217,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 调用 `build_consumer` 函数尝试获取消费者实例 `tmq`。成功则打印成功日志,失败则打印失败日志。 - + +不支持 + ## 订阅消费数据 @@ -267,7 +280,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 {{#include docs/examples/csharp/wssubscribe/Program.cs:subscribe}} ```
- + +不支持 + + +不支持 + ### 原生连接 @@ -311,7 +329,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 - `Record` 是我们自定义的一个结构体,其字段名和数据类型与列的名称和数据类型一一对应,这样可以通过 `serde` 反序列化出 `Record` 类型的对象。
- + +不支持 + ```csharp {{#include docs/examples/csharp/subscribe/Program.cs:subscribe}} @@ -343,7 +363,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 5. 调用 `basic_consume_loop` 函数开始基本的消费循环,处理订阅的消息。 - + +不支持 + ## 指定订阅的 Offset @@ -402,6 +424,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 {{#include docs/examples/csharp/wssubscribe/Program.cs:seek}} ```
+ +不支持 + + +不支持 + ### 原生连接 @@ -445,7 +473,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 2. 在所有分区的偏移量调整完成后,再次获取并记录消费者的分区分配信息,以确认偏移量调整后的状态。
- + +不支持 + ```csharp {{#include docs/examples/csharp/subscribe/Program.cs:seek}} @@ -465,6 +495,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 6. 调用 `basic_consume_loop` 函数开始新的的消费循环,处理消息。 + +不支持 + @@ -518,6 +551,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 {{#include docs/examples/csharp/wssubscribe/Program.cs:commit_offset}} ```
+ +不支持 + + +不支持 + ### 原生连接 @@ -551,7 +590,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 可以通过 `consumer.commit` 方法来手工提交消费进度。
- + +不支持 + ```csharp {{#include docs/examples/csharp/subscribe/Program.cs:commit_offset}} @@ -566,6 +607,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 可以通过 `tmq_commit_sync` 函数来手工提交消费进度。 + +不支持 + @@ -615,6 +659,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 {{#include docs/examples/csharp/wssubscribe/Program.cs:close}} ``` + +不支持 + + +不支持 + ### 原生连接 @@ -646,7 +696,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 **注意**:消费者取消订阅后无法重用,如果想订阅新的 `topic`, 请重新创建消费者。 - + +不支持 + ```csharp {{#include docs/examples/csharp/subscribe/Program.cs:close}} @@ -658,7 +710,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 {{#include docs/examples/c/tmq_demo.c:unsubscribe_and_close}} ``` - + +不支持 + @@ -720,7 +774,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 ``` - + +不支持 + + +不支持 + ### 原生连接 @@ -765,7 +824,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 ``` - + +不支持 +
完整代码示例 @@ -783,4 +844,7 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请 ```
+ +不支持 + diff --git a/docs/zh/14-reference/05-connector/index.md b/docs/zh/14-reference/05-connector/index.md index 5c58a4e7bc..6cca1960c3 100644 --- a/docs/zh/14-reference/05-connector/index.md +++ b/docs/zh/14-reference/05-connector/index.md @@ -46,10 +46,10 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器 | **功能特性** | **Java** | **Python** | **Go** | **C#** | **Rust** | | ------------------- | -------- | ---------- | ------ | ------ | -------- | | **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | +| **执行 SQL** | 支持 | 支持 | 支持 | 支持 | 支持 | | **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | | **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | +| **无模式写入** | 支持 | 支持 | 支持 | 支持 | 支持 | :::info 由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。 @@ -57,20 +57,20 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器 ### 使用 http REST 接口 -| **功能特性** | **Java** | **Python** | **Go** | **C#** | -| ------------ | -------- | ---------- | ------ | ------ | -| **连接管理** | 支持 | 支持 | 支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | +| **功能特性** | **Java** | **Python** | **Go** | +| ------------ | -------- | ---------- | ------ | +| **连接管理** | 支持 | 支持 | 支持 | +| **执行 SQL** | 支持 | 支持 | 支持 | ### 使用 Websocket 接口 | **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | | ------------------- | -------- | ---------- | ------ | ------ | ----------- | -------- | | **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **执行 SQL** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | | **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | | **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **无模式写入** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | :::warning - 无论选用何种编程语言的连接器,2.0 及以上版本的 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池,以避免连接内的“USE statement”状态量在线程之间相互干扰(但连接的查询和写入操作都是线程安全的)。 @@ -128,4 +128,4 @@ import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -``` \ No newline at end of file +```