From af1096522c0bd5ec03ce4cbeb4183aa582cf3b04 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Fri, 1 Nov 2024 15:19:02 +0800 Subject: [PATCH 01/60] set default compress --- source/common/src/tcol.c | 16 ++++++++++++++++ tests/script/tsim/compress/compress2.sim | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/source/common/src/tcol.c b/source/common/src/tcol.c index 84027c25b6..07a76e5785 100644 --- a/source/common/src/tcol.c +++ b/source/common/src/tcol.c @@ -81,26 +81,42 @@ const char* getDefaultEncodeStr(uint8_t type) { return columnEncodeStr(getDefaul uint16_t getDefaultCompress(uint8_t type) { switch (type) { case TSDB_DATA_TYPE_NULL: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_BOOL: + return TSDB_COLVAL_COMPRESS_ZSTD; case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: + return TSDB_COLVAL_COMPRESS_ZLIB; case TSDB_DATA_TYPE_INT: case TSDB_DATA_TYPE_BIGINT: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_DOUBLE: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_VARCHAR: // TSDB_DATA_TYPE_BINARY + return TSDB_COLVAL_COMPRESS_ZSTD; case TSDB_DATA_TYPE_TIMESTAMP: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_NCHAR: + return TSDB_COLVAL_COMPRESS_ZSTD; case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_USMALLINT: + return TSDB_COLVAL_COMPRESS_ZLIB; case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_UBIGINT: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_JSON: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_VARBINARY: + return TSDB_COLVAL_COMPRESS_ZSTD; case TSDB_DATA_TYPE_DECIMAL: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_BLOB: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_MEDIUMBLOB: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_GEOMETRY: + return TSDB_COLVAL_COMPRESS_LZ4; case TSDB_DATA_TYPE_MAX: return TSDB_COLVAL_COMPRESS_LZ4; default: diff --git a/tests/script/tsim/compress/compress2.sim b/tests/script/tsim/compress/compress2.sim index 0af6f87de4..179317dfbb 100644 --- a/tests/script/tsim/compress/compress2.sim +++ b/tests/script/tsim/compress/compress2.sim @@ -38,7 +38,7 @@ sql alter table $tb modify column b level 'm' sql_error alter table $tb modify column b level 'l' # already exist -sql_error alter table $tb modify column b compress 'lz4' +sql alter table $tb modify column b compress 'lz4' sql alter table $tb modify column b compress 'xz' sql alter table $tb modify column b compress 'zstd' sql_error alter table $tb modify column b compress 'tsz' @@ -147,7 +147,7 @@ sql alter table $stb modify column b level 'm' sql_error alter table $stb modify column b level 'l' # already exist sql desc $stb -sql_error alter table $stb modify column b compress 'lz4' +sql alter table $stb modify column b compress 'lz4' sql alter table $stb modify column b compress 'xz' sql alter table $stb modify column b compress 'zstd' sql_error alter table $stb modify column b compress 'tsz' From 6720f850b0a1eb2a9e07c4ef0b47d6723e10b006 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Tue, 12 Nov 2024 10:12:30 +0800 Subject: [PATCH 02/60] fix: print multi dataDir for show variables --- source/common/src/tmisce.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/source/common/src/tmisce.c b/source/common/src/tmisce.c index 4df458c2bb..1fd590bf79 100644 --- a/source/common/src/tmisce.c +++ b/source/common/src/tmisce.c @@ -267,7 +267,11 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol) { int8_t locked = 0; - TAOS_CHECK_GOTO(blockDataEnsureCapacity(pBlock, cfgGetSize(pConf)), NULL, _exit); + SConfigItem* pDataDirItem = cfgGetItem(pConf, "dataDir"); + size_t exSize = TMAX(taosArrayGetSize(pDataDirItem->array), 1) - 1; + size_t index = 0; + + TAOS_CHECK_GOTO(blockDataEnsureCapacity(pBlock, cfgGetSize(pConf) + exSize), NULL, _exit); TAOS_CHECK_GOTO(cfgCreateIter(pConf, &pIter), NULL, _exit); @@ -275,6 +279,7 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol) { locked = 1; while ((pItem = cfgNextIter(pIter)) != NULL) { +_start: col = startCol; // GRANT_CFG_SKIP; @@ -291,7 +296,17 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol) { char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0}; int32_t valueLen = 0; - TAOS_CHECK_GOTO(cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen), NULL, _exit); + + if (strcasecmp(pItem->name, "dataDir") == 0 && exSize > 0) { + char* buf = &value[VARSTR_HEADER_SIZE]; + SDiskCfg* pDiskCfg = taosArrayGet(pItem->array, index); + valueLen = snprintf(buf, TSDB_CONFIG_VALUE_LEN, "%s l:%d p:%d d:%" PRIi8, pDiskCfg->dir, pDiskCfg->level, + pDiskCfg->primary, pDiskCfg->disable); + index++; + } else { + TAOS_CHECK_GOTO(cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen), NULL, + _exit); + } varDataSetLen(value, valueLen); pColInfo = taosArrayGet(pBlock->pDataBlock, col++); @@ -314,7 +329,10 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol) { TAOS_CHECK_GOTO(colDataSetVal(pColInfo, numOfRows, scope, false), NULL, _exit); numOfRows++; - } + if (index > 0 && index <= exSize) { + goto _start; + } +} pBlock->info.rows = numOfRows; _exit: if (locked) cfgUnLock(pConf); From a3fa03646a99b644482317d4ae16b4e05da0a487 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Tue, 12 Nov 2024 15:17:43 +0800 Subject: [PATCH 03/60] fix: print multi dataDir for log --- source/util/src/tconfig.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index d6852b0566..10bebc1907 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -881,11 +881,26 @@ void cfgDumpCfg(SConfig *pCfg, bool tsc, bool dump) { case CFG_DTYPE_CHARSET: case CFG_DTYPE_TIMEZONE: case CFG_DTYPE_NONE: + if (strcasecmp(pItem->name, "dataDir") == 0) { + size_t sz = taosArrayGetSize(pItem->array); + if (sz > 1) { + for (size_t j = 0; j < sz; ++j) { + SDiskCfg *pCfg = taosArrayGet(pItem->array, j); + if (dump) { + (void)printf("%s %s %s l:%d p:%d d:%"PRIi8"\n", src, name, pCfg->dir, pCfg->level, pCfg->primary, pCfg->disable); + } else { + uInfo("%s %s %s l:%d p:%d d:%"PRIi8, src, name, pCfg->dir, pCfg->level, pCfg->primary, pCfg->disable); + } + } + break; + } + } if (dump) { (void)printf("%s %s %s\n", src, name, pItem->str); } else { uInfo("%s %s %s", src, name, pItem->str); } + break; } } From 5f5e000160035005d094fb8031ebafdedb8f7f11 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Tue, 12 Nov 2024 16:37:14 +0800 Subject: [PATCH 04/60] fix: show local issue --- source/common/src/tmisce.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/common/src/tmisce.c b/source/common/src/tmisce.c index 1fd590bf79..0ac59ef4a4 100644 --- a/source/common/src/tmisce.c +++ b/source/common/src/tmisce.c @@ -267,9 +267,12 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol) { int8_t locked = 0; - SConfigItem* pDataDirItem = cfgGetItem(pConf, "dataDir"); - size_t exSize = TMAX(taosArrayGetSize(pDataDirItem->array), 1) - 1; + size_t exSize = 0; size_t index = 0; + SConfigItem* pDataDirItem = cfgGetItem(pConf, "dataDir"); + if (pDataDirItem) { + exSize = TMAX(taosArrayGetSize(pDataDirItem->array), 1) - 1; + } TAOS_CHECK_GOTO(blockDataEnsureCapacity(pBlock, cfgGetSize(pConf) + exSize), NULL, _exit); From 67a547f65a1acaa5637d74dc3037181b37e6edad Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 13 Nov 2024 13:46:23 +0800 Subject: [PATCH 05/60] fix(stream): alwasy return success for resume req. --- source/dnode/vnode/src/tqCommon/tqCommon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/dnode/vnode/src/tqCommon/tqCommon.c b/source/dnode/vnode/src/tqCommon/tqCommon.c index f31dd28847..326e8d4ada 100644 --- a/source/dnode/vnode/src/tqCommon/tqCommon.c +++ b/source/dnode/vnode/src/tqCommon/tqCommon.c @@ -1186,10 +1186,12 @@ int32_t tqStreamTaskProcessTaskResumeReq(void* handle, int64_t sversion, char* m streamMutexUnlock(&pHTask->lock); code = tqProcessTaskResumeImpl(handle, pHTask, sversion, pReq->igUntreated, fromVnode); + tqDebug("s-task:%s resume complete, code:%s", pHTask->id.idStr, tstrerror(code)); + streamMetaReleaseTask(pMeta, pHTask); } - return code; + return TSDB_CODE_SUCCESS; } int32_t tqStreamTasksGetTotalNum(SStreamMeta* pMeta) { return taosArrayGetSize(pMeta->pTaskList); } From 67da7b103660369620069b83bb0b7ffe5fc0b7bf Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Wed, 13 Nov 2024 16:51:40 +0800 Subject: [PATCH 06/60] feat: alter systable variablesSchema --- include/common/tmsg.h | 3 ++- include/libs/nodes/cmdnodes.h | 5 +++-- include/util/tdef.h | 10 +++++---- source/client/inc/clientInt.h | 3 ++- source/client/src/clientMsgHandler.c | 15 ++++++++++++-- source/common/src/systable.c | 3 ++- source/common/src/tmisce.c | 28 ++++++++++++++++++++------ source/dnode/mnode/impl/src/mndDnode.c | 1 + source/libs/command/src/command.c | 6 ++++++ source/libs/parser/src/parTranslater.c | 16 +++++++++------ 10 files changed, 67 insertions(+), 23 deletions(-) diff --git a/include/common/tmsg.h b/include/common/tmsg.h index a7da778513..70a32cd266 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -2187,8 +2187,9 @@ int32_t tSerializeSShowVariablesReq(void* buf, int32_t bufLen, SShowVariablesReq typedef struct { char name[TSDB_CONFIG_OPTION_LEN + 1]; - char value[TSDB_CONFIG_VALUE_LEN + 1]; + char value[TSDB_CONFIG_PATH_LEN + 1]; char scope[TSDB_CONFIG_SCOPE_LEN + 1]; + char info[TSDB_CONFIG_INFO_LEN + 1]; } SVariablesInfo; typedef struct { diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h index 514eddbc24..0b617c7ce3 100644 --- a/include/libs/nodes/cmdnodes.h +++ b/include/libs/nodes/cmdnodes.h @@ -42,10 +42,11 @@ extern "C" { #define SHOW_CREATE_VIEW_RESULT_FIELD1_LEN (TSDB_VIEW_FNAME_LEN + 4 + VARSTR_HEADER_SIZE) #define SHOW_CREATE_VIEW_RESULT_FIELD2_LEN (TSDB_MAX_ALLOWED_SQL_LEN + VARSTR_HEADER_SIZE) -#define SHOW_LOCAL_VARIABLES_RESULT_COLS 3 +#define SHOW_LOCAL_VARIABLES_RESULT_COLS 4 #define SHOW_LOCAL_VARIABLES_RESULT_FIELD1_LEN (TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE) -#define SHOW_LOCAL_VARIABLES_RESULT_FIELD2_LEN (TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE) +#define SHOW_LOCAL_VARIABLES_RESULT_FIELD2_LEN (TSDB_CONFIG_PATH_LEN + VARSTR_HEADER_SIZE) #define SHOW_LOCAL_VARIABLES_RESULT_FIELD3_LEN (TSDB_CONFIG_SCOPE_LEN + VARSTR_HEADER_SIZE) +#define SHOW_LOCAL_VARIABLES_RESULT_FIELD4_LEN (TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE) #define COMPACT_DB_RESULT_COLS 3 #define COMPACT_DB_RESULT_FIELD1_LEN 32 diff --git a/include/util/tdef.h b/include/util/tdef.h index ba30e78c59..695b4159fd 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -195,9 +195,9 @@ static const EOperatorType OPERATOR_ARRAY[] = { OP_TYPE_MULTI, OP_TYPE_DIV, OP_TYPE_REM, - + OP_TYPE_MINUS, - + OP_TYPE_BIT_AND, OP_TYPE_BIT_OR, @@ -213,7 +213,7 @@ static const EOperatorType OPERATOR_ARRAY[] = { OP_TYPE_NOT_LIKE, OP_TYPE_MATCH, OP_TYPE_NMATCH, - + OP_TYPE_IS_NULL, OP_TYPE_IS_NOT_NULL, OP_TYPE_IS_TRUE, @@ -222,7 +222,7 @@ static const EOperatorType OPERATOR_ARRAY[] = { OP_TYPE_IS_NOT_TRUE, OP_TYPE_IS_NOT_FALSE, OP_TYPE_IS_NOT_UNKNOWN, - //OP_TYPE_COMPARE_MAX_VALUE, + //OP_TYPE_COMPARE_MAX_VALUE, OP_TYPE_JSON_GET_VALUE, OP_TYPE_JSON_CONTAINS, @@ -631,6 +631,8 @@ enum { RAND_ERR_MEMORY = 1, RAND_ERR_FILE = 2, RAND_ERR_NETWORK = 4 }; #define TSDB_CONFIG_VALUE_LEN 64 #define TSDB_CONFIG_SCOPE_LEN 8 #define TSDB_CONFIG_NUMBER 16 +#define TSDB_CONFIG_PATH_LEN 128 +#define TSDB_CONFIG_INFO_LEN 64 #define QUERY_ID_SIZE 20 #define QUERY_OBJ_ID_SIZE 18 diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 90505ed25a..da56dcf75e 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -47,10 +47,11 @@ enum { RES_TYPE__TMQ_BATCH_META, }; -#define SHOW_VARIABLES_RESULT_COLS 3 +#define SHOW_VARIABLES_RESULT_COLS 4 #define SHOW_VARIABLES_RESULT_FIELD1_LEN (TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE) #define SHOW_VARIABLES_RESULT_FIELD2_LEN (TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE) #define SHOW_VARIABLES_RESULT_FIELD3_LEN (TSDB_CONFIG_SCOPE_LEN + VARSTR_HEADER_SIZE) +#define SHOW_VARIABLES_RESULT_FIELD4_LEN (TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE) #define TD_RES_QUERY(res) (*(int8_t*)(res) == RES_TYPE__QUERY) #define TD_RES_TMQ(res) (*(int8_t*)(res) == RES_TYPE__TMQ) diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c index 9a723218ff..e182cd97ee 100644 --- a/source/client/src/clientMsgHandler.c +++ b/source/client/src/clientMsgHandler.c @@ -541,6 +541,10 @@ static int32_t buildShowVariablesBlock(SArray* pVars, SSDataBlock** block) { infoData.info.bytes = SHOW_VARIABLES_RESULT_FIELD3_LEN; TSDB_CHECK_NULL(taosArrayPush(pBlock->pDataBlock, &infoData), code, line, END, terrno); + infoData.info.type = TSDB_DATA_TYPE_VARCHAR; + infoData.info.bytes = SHOW_VARIABLES_RESULT_FIELD4_LEN; + TSDB_CHECK_NULL(taosArrayPush(pBlock->pDataBlock, &infoData), code, line, END, terrno); + int32_t numOfCfg = taosArrayGetSize(pVars); code = blockDataEnsureCapacity(pBlock, numOfCfg); TSDB_CHECK_CODE(code, line, END); @@ -569,6 +573,13 @@ static int32_t buildShowVariablesBlock(SArray* pVars, SSDataBlock** block) { TSDB_CHECK_NULL(pColInfo, code, line, END, terrno); code = colDataSetVal(pColInfo, i, scope, false); TSDB_CHECK_CODE(code, line, END); + + char info[TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(info, pInfo->info, TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE); + pColInfo = taosArrayGet(pBlock->pDataBlock, c++); + TSDB_CHECK_NULL(pColInfo, code, line, END, terrno); + code = colDataSetVal(pColInfo, i, info, false); + TSDB_CHECK_CODE(code, line, END); } pBlock->info.rows = numOfCfg; @@ -825,7 +836,7 @@ int32_t processCompactDbRsp(void* param, SDataBuf* pMsg, int32_t code) { tscError("failed to post semaphore"); } } - return code; + return code; } __async_send_cb_fn_t getMsgRspHandle(int32_t msgType) { @@ -845,7 +856,7 @@ __async_send_cb_fn_t getMsgRspHandle(int32_t msgType) { case TDMT_MND_SHOW_VARIABLES: return processShowVariablesRsp; case TDMT_MND_COMPACT_DB: - return processCompactDbRsp; + return processCompactDbRsp; default: return genericRspCallback; } diff --git a/source/common/src/systable.c b/source/common/src/systable.c index 4993ece7c1..12b789f14e 100644 --- a/source/common/src/systable.c +++ b/source/common/src/systable.c @@ -327,8 +327,9 @@ static const SSysDbTableSchema configSchema[] = { static const SSysDbTableSchema variablesSchema[] = { {.name = "dnode_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = true}, {.name = "name", .bytes = TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, - {.name = "value", .bytes = TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, + {.name = "value", .bytes = TSDB_CONFIG_PATH_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, {.name = "scope", .bytes = TSDB_CONFIG_SCOPE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, + {.name = "info", .bytes = TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, }; static const SSysDbTableSchema topicSchema[] = { diff --git a/source/common/src/tmisce.c b/source/common/src/tmisce.c index 0ac59ef4a4..dfba2ebf6c 100644 --- a/source/common/src/tmisce.c +++ b/source/common/src/tmisce.c @@ -297,17 +297,16 @@ _start: TAOS_CHECK_GOTO(colDataSetVal(pColInfo, numOfRows, name, false), NULL, _exit); - char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0}; + char value[TSDB_CONFIG_PATH_LEN + VARSTR_HEADER_SIZE] = {0}; int32_t valueLen = 0; - + SDiskCfg* pDiskCfg = NULL; if (strcasecmp(pItem->name, "dataDir") == 0 && exSize > 0) { char* buf = &value[VARSTR_HEADER_SIZE]; - SDiskCfg* pDiskCfg = taosArrayGet(pItem->array, index); - valueLen = snprintf(buf, TSDB_CONFIG_VALUE_LEN, "%s l:%d p:%d d:%" PRIi8, pDiskCfg->dir, pDiskCfg->level, - pDiskCfg->primary, pDiskCfg->disable); + pDiskCfg = taosArrayGet(pItem->array, index); + valueLen = tsnprintf(buf, TSDB_CONFIG_PATH_LEN, "%s", pDiskCfg->dir); index++; } else { - TAOS_CHECK_GOTO(cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen), NULL, + TAOS_CHECK_GOTO(cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_PATH_LEN, &valueLen), NULL, _exit); } varDataSetLen(value, valueLen); @@ -331,6 +330,23 @@ _start: } TAOS_CHECK_GOTO(colDataSetVal(pColInfo, numOfRows, scope, false), NULL, _exit); + char info[TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE] = {0}; + if (strcasecmp(pItem->name, "dataDir") == 0) { + char* buf = &info[VARSTR_HEADER_SIZE]; + valueLen = tsnprintf(buf, TSDB_CONFIG_INFO_LEN, "level %d primary %d disabled %" PRIi8, pDiskCfg->level, + pDiskCfg->primary, pDiskCfg->disable); + } else { + valueLen = 0; + } + varDataSetLen(info, valueLen); + + pColInfo = taosArrayGet(pBlock->pDataBlock, col++); + if (pColInfo == NULL) { + code = terrno; + TAOS_CHECK_GOTO(code, NULL, _exit); + } + TAOS_CHECK_GOTO(colDataSetVal(pColInfo, numOfRows, info, false), NULL, _exit); + numOfRows++; if (index > 0 && index <= exSize) { goto _start; diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index 24ae8382f9..8931558874 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -1104,6 +1104,7 @@ static int32_t mndProcessShowVariablesReq(SRpcMsg *pReq) { (void)strcpy(info.name, "statusInterval"); (void)snprintf(info.value, TSDB_CONFIG_VALUE_LEN, "%d", tsStatusInterval); (void)strcpy(info.scope, "server"); + // fill info.info if (taosArrayPush(rsp.variables, &info) == NULL) { code = terrno; goto _OVER; diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 5afdf87afb..6689b5541b 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -953,6 +953,12 @@ static int32_t buildLocalVariablesResultDataBlock(SSDataBlock** pOutput) { goto _exit; } + infoData.info.type = TSDB_DATA_TYPE_VARCHAR; + infoData.info.bytes = SHOW_LOCAL_VARIABLES_RESULT_FIELD4_LEN; + if (taosArrayPush(pBlock->pDataBlock, &infoData) == NULL) { + goto _exit; + } + *pOutput = pBlock; _exit: diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 99c03c412c..9bea3491c3 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -3311,11 +3311,11 @@ static int32_t selectCommonType(SDataType* commonType, const SDataType* newType) } else { resultType = gDisplyTypes[type2][type1]; } - + if (resultType == -1) { return TSDB_CODE_SCALAR_CONVERT_ERROR; } - + if (commonType->type == newType->type) { commonType->bytes = TMAX(commonType->bytes, newType->bytes); return TSDB_CODE_SUCCESS; @@ -3328,9 +3328,9 @@ static int32_t selectCommonType(SDataType* commonType, const SDataType* newType) } else { commonType->bytes = TMAX(TMAX(commonType->bytes, newType->bytes), TYPE_BYTES[resultType]); } - + commonType->type = resultType; - + return TSDB_CODE_SUCCESS; } @@ -13127,7 +13127,7 @@ static int32_t extractShowCreateViewResultSchema(int32_t* numOfCols, SSchema** p } static int32_t extractShowVariablesResultSchema(int32_t* numOfCols, SSchema** pSchema) { - *numOfCols = 3; + *numOfCols = SHOW_LOCAL_VARIABLES_RESULT_COLS; // SHOW_VARIABLES_RESULT_COLS *pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema)); if (NULL == (*pSchema)) { return terrno; @@ -13138,13 +13138,17 @@ static int32_t extractShowVariablesResultSchema(int32_t* numOfCols, SSchema** pS strcpy((*pSchema)[0].name, "name"); (*pSchema)[1].type = TSDB_DATA_TYPE_BINARY; - (*pSchema)[1].bytes = TSDB_CONFIG_VALUE_LEN; + (*pSchema)[1].bytes = TSDB_CONFIG_PATH_LEN; strcpy((*pSchema)[1].name, "value"); (*pSchema)[2].type = TSDB_DATA_TYPE_BINARY; (*pSchema)[2].bytes = TSDB_CONFIG_SCOPE_LEN; strcpy((*pSchema)[2].name, "scope"); + (*pSchema)[3].type = TSDB_DATA_TYPE_BINARY; + (*pSchema)[3].bytes = TSDB_CONFIG_INFO_LEN; + strcpy((*pSchema)[3].name, "info"); + return TSDB_CODE_SUCCESS; } From 9a9f463877fb9162c0048c9cd3e1bc0f2a83ec59 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Wed, 13 Nov 2024 16:53:56 +0800 Subject: [PATCH 07/60] feat: alter TSDB_CONFIG_PATH_LEN from 128 to 4096 --- include/util/tdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/util/tdef.h b/include/util/tdef.h index 695b4159fd..4e1fb21838 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -631,7 +631,7 @@ enum { RAND_ERR_MEMORY = 1, RAND_ERR_FILE = 2, RAND_ERR_NETWORK = 4 }; #define TSDB_CONFIG_VALUE_LEN 64 #define TSDB_CONFIG_SCOPE_LEN 8 #define TSDB_CONFIG_NUMBER 16 -#define TSDB_CONFIG_PATH_LEN 128 +#define TSDB_CONFIG_PATH_LEN 4096 #define TSDB_CONFIG_INFO_LEN 64 #define QUERY_ID_SIZE 20 From 1c6976ca09af0679b98cb86e5d8c1b81deb9ac24 Mon Sep 17 00:00:00 2001 From: wangjiaming0909 <604227650@qq.com> Date: Wed, 13 Nov 2024 17:07:53 +0800 Subject: [PATCH 08/60] fix eliminate proj caused crash --- source/libs/planner/src/planOptimizer.c | 80 ++++++++++++++++++------- tests/system-test/2-query/union.py | 33 ++++++++++ 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 885faa5461..b179c58ee1 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -3491,38 +3491,69 @@ static void eliminateProjPushdownProjIdx(SNodeList* pParentProjects, SNodeList* } } +static int32_t eliminateProjOptFindProjPrefixWithOrderCheck(SProjectLogicNode* pProj, SProjectLogicNode* pChild, SNodeList** pNewChildTargets, bool *orderMatch) { + int32_t code = 0; + SNode* pProjection = NULL, *pChildTarget = NULL; + *orderMatch = true; + FORBOTH(pProjection, pProj->pProjections, pChildTarget, pChild->node.pTargets) { + if (!pProjection) break; + if (0 != strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) { + *orderMatch = false; + break; + } + SNode* pNew = NULL; + code = nodesCloneNode(pChildTarget, &pNew); + if (TSDB_CODE_SUCCESS == code) { + code = nodesListMakeStrictAppend(pNewChildTargets, pNew); + } + if (TSDB_CODE_SUCCESS != code && pNewChildTargets) { + nodesDestroyList(*pNewChildTargets); + *pNewChildTargets = NULL; + break; + } + } + return code; +} + +static int32_t eliminateProjOptPushTargetsToSetOpChildren(SProjectLogicNode* pSetOp) { + SNode* pChildProj = NULL; + int32_t code = 0; + bool orderMatch = false; + FOREACH(pChildProj, pSetOp->node.pChildren) { + if (QUERY_NODE_LOGIC_PLAN_PROJECT == nodeType(pChildProj)) { + SProjectLogicNode* pChildLogic = (SProjectLogicNode*)pChildProj; + SNodeList* pNewChildTargetsForChild = NULL; + code = eliminateProjOptFindProjPrefixWithOrderCheck(pSetOp, pChildLogic, &pNewChildTargetsForChild, &orderMatch); + if (TSDB_CODE_SUCCESS != code) break; + nodesDestroyList(pChildLogic->node.pTargets); + pChildLogic->node.pTargets = pNewChildTargetsForChild; + alignProjectionWithTarget((SLogicNode*)pChildLogic); + if (pChildLogic->isSetOpProj) { + code = eliminateProjOptPushTargetsToSetOpChildren(pChildLogic); + if (TSDB_CODE_SUCCESS != code) break; + } + } + } + return code; +} + static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SProjectLogicNode* pProjectNode) { SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pProjectNode->node.pChildren, 0); int32_t code = 0; + bool isSetOpProj = false; + bool orderMatch = false; if (NULL == pProjectNode->node.pParent) { SNodeList* pNewChildTargets = NULL; - code = nodesMakeList(&pNewChildTargets); - if (TSDB_CODE_SUCCESS != code) { - return code; - } SNode * pProjection = NULL, *pChildTarget = NULL; - bool orderMatch = true; - bool needOrderMatch = + isSetOpProj = QUERY_NODE_LOGIC_PLAN_PROJECT == nodeType(pChild) && ((SProjectLogicNode*)pChild)->isSetOpProj; - if (needOrderMatch) { + if (isSetOpProj) { // For sql: select ... from (select ... union all select ...); // When eliminating the outer proj (the outer select), we have to make sure that the outer proj projections and // union all project targets have same columns in the same order. See detail in TD-30188 - FORBOTH(pProjection, pProjectNode->pProjections, pChildTarget, pChild->pTargets) { - if (!pProjection) break; - if (0 != strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) { - orderMatch = false; - break; - } - SNode* pNew = NULL; - code = nodesCloneNode(pChildTarget, &pNew); - if (TSDB_CODE_SUCCESS == code) { - code = nodesListStrictAppend(pNewChildTargets, pNew); - } - if (TSDB_CODE_SUCCESS != code) break; - } + code = eliminateProjOptFindProjPrefixWithOrderCheck(pProjectNode, (SProjectLogicNode*)pChild, &pNewChildTargets, &orderMatch); } else { FOREACH(pProjection, pProjectNode->pProjections) { FOREACH(pChildTarget, pChild->pTargets) { @@ -3530,7 +3561,7 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* SNode* pNew = NULL; code = nodesCloneNode(pChildTarget, &pNew); if (TSDB_CODE_SUCCESS == code) { - code = nodesListStrictAppend(pNewChildTargets, pNew); + code = nodesListMakeStrictAppend(&pNewChildTargets, pNew); } break; } @@ -3545,8 +3576,7 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* return code; } - if (eliminateProjOptCanChildConditionUseChildTargets(pChild, pNewChildTargets) && - (!needOrderMatch || (needOrderMatch && orderMatch))) { + if (eliminateProjOptCanChildConditionUseChildTargets(pChild, pNewChildTargets) && (!isSetOpProj || orderMatch)) { nodesDestroyList(pChild->pTargets); pChild->pTargets = pNewChildTargets; } else { @@ -3574,6 +3604,10 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* nodesDestroyNode((SNode*)pProjectNode); // if pChild is a project logic node, remove its projection which is not reference by its target. alignProjectionWithTarget(pChild); + if (isSetOpProj && orderMatch) { + // Since we have eliminated the outer proj, we need to push down the new targets to the children of the set operation. + code = eliminateProjOptPushTargetsToSetOpChildren((SProjectLogicNode*)pChild); + } } pCxt->optimized = true; return code; diff --git a/tests/system-test/2-query/union.py b/tests/system-test/2-query/union.py index 2aa01f2c02..b74db0104d 100644 --- a/tests/system-test/2-query/union.py +++ b/tests/system-test/2-query/union.py @@ -369,8 +369,41 @@ class TDTestCase: ''' ) + def test_TS_5630(self): + sql = "CREATE DATABASE `ep_iot` BUFFER 256 CACHESIZE 20 CACHEMODEL 'both' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 2 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 3 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 3600 WAL_RETENTION_SIZE 0" + tdSql.execute(sql, queryTimes=1) + tdLog.info("database ep_iot created") + sql = "CREATE STABLE `ep_iot`.`sldc_dp` (`ts` TIMESTAMP, `data_write_time` TIMESTAMP, `jz1fdgl` DOUBLE, `jz1ssfdfh` DOUBLE, `jz1fdmh` DOUBLE, `jz1gdmh` DOUBLE, `jz1qjrhl` DOUBLE, `jz1zhcydl` DOUBLE, `jz1zkby` DOUBLE, `jz1zzqyl` DOUBLE, `jz1zzqwda` DOUBLE, `jz1zzqwdb` DOUBLE, `jz1zzqll` DOUBLE, `jz1gswd` DOUBLE, `jz1gsll` DOUBLE, `jz1glxl` DOUBLE, `jz1qjrh` DOUBLE, `jz1zhrxl` DOUBLE, `jz1gmjassllfk` DOUBLE, `jz1gmjasslllj` DOUBLE, `jz1gmjbssllfk` DOUBLE, `jz1gmjbsslllj` DOUBLE, `jz1gmjcssllfk` DOUBLE, `jz1gmjcsslllj` DOUBLE, `jz1gmjdssllfk` DOUBLE, `jz1gmjdsslllj` DOUBLE, `jz1gmjessllfk` DOUBLE, `jz1gmjesslllj` DOUBLE, `jz1gmjfssllfk` DOUBLE, `jz1gmjfsslllj` DOUBLE, `jz1zrqwda` DOUBLE, `jz1zrqwdb` DOUBLE, `jz1zrzqyl` DOUBLE, `jz1mmjadl` DOUBLE, `jz1mmjbdl` DOUBLE, `jz1mmjcdl` DOUBLE, `jz1mmjddl` DOUBLE, `jz1mmjedl` DOUBLE, `jz1mmjfdl` DOUBLE, `jz1cyqckwda` DOUBLE, `jz1cyqckwdb` DOUBLE, `jz1njswd` DOUBLE, `jz1nqqxhsckawd` DOUBLE, `jz1nqqxhsckbwd` DOUBLE, `jz1nqqxhsrkawd` DOUBLE, `jz1nqqxhsrkbwd` DOUBLE, `jz1kyqackyqwdsel` DOUBLE, `jz1kyqbckyqwdsel` DOUBLE, `jz1yfjackyqwd` DOUBLE, `jz1yfjbckyqwd` DOUBLE, `jz1trkyqwd` DOUBLE, `jz1trkyqwd1` DOUBLE, `jz1trkyqwd2` DOUBLE, `jz1trkyqwd3` DOUBLE, `jz1tckjyqwd1` DOUBLE, `jz1tckjyqwd2` DOUBLE, `jz1tckyqwd1` DOUBLE, `jz1bya` DOUBLE, `jz1byb` DOUBLE, `jz1pqwda` DOUBLE, `jz1pqwdb` DOUBLE, `jz1gmjadl` DOUBLE, `jz1gmjbdl` DOUBLE, `jz1gmjcdl` DOUBLE, `jz1gmjddl` DOUBLE, `jz1gmjedl` DOUBLE, `jz1gmjfdl` DOUBLE, `jz1yfjadl` DOUBLE, `jz1yfjbdl` DOUBLE, `jz1ycfjadl` DOUBLE, `jz1ycfjbdl` DOUBLE, `jz1sfjadl` DOUBLE, `jz1sfjbdl` DOUBLE, `jz1fdjyggl` DOUBLE, `jz1fdjwggl` DOUBLE, `jz1sjzs` DOUBLE, `jz1zfl` DOUBLE, `jz1ltyl` DOUBLE, `jz1smb` DOUBLE, `jz1rll` DOUBLE, `jz1grd` DOUBLE, `jz1zjwd` DOUBLE, `jz1yl` DOUBLE, `jz1kyqckwd` DOUBLE, `jz1abmfsybrkcy` DOUBLE, `jz1bbmfsybrkcy` DOUBLE, `jz1abjcsdmfytwdzdz` DOUBLE, `jz1bbjcsdmfytwdzdz` DOUBLE, `jz2fdgl` DOUBLE, `jz2ssfdfh` DOUBLE, `jz2fdmh` DOUBLE, `jz2gdmh` DOUBLE, `jz2qjrhl` DOUBLE, `jz2zhcydl` DOUBLE, `jz2zkby` DOUBLE, `jz2zzqyl` DOUBLE, `jz2zzqwda` DOUBLE, `jz2zzqwdb` DOUBLE, `jz2zzqll` DOUBLE, `jz2gswd` DOUBLE, `jz2gsll` DOUBLE, `jz2glxl` DOUBLE, `jz2qjrh` DOUBLE, `jz2zhrxl` DOUBLE, `jz2gmjassllfk` DOUBLE, `jz2gmjasslllj` DOUBLE, `jz2gmjbssllfk` DOUBLE, `jz2gmjbsslllj` DOUBLE, `jz2gmjcssllfk` DOUBLE, `jz2gmjcsslllj` DOUBLE, `jz2gmjdssllfk` DOUBLE, `jz2gmjdsslllj` DOUBLE, `jz2gmjessllfk` DOUBLE, `jz2gmjesslllj` DOUBLE, `jz2gmjfssllfk` DOUBLE, `jz2gmjfsslllj` DOUBLE, `jz2zrqwda` DOUBLE, `jz2zrqwdb` DOUBLE, `jz2zrzqyl` DOUBLE, `jz2mmjadl` DOUBLE, `jz2mmjbdl` DOUBLE, `jz2mmjcdl` DOUBLE, `jz2mmjddl` DOUBLE, `jz2mmjedl` DOUBLE, `jz2mmjfdl` DOUBLE, `jz2cyqckwda` DOUBLE, `jz2cyqckwdb` DOUBLE, `jz2njswd` DOUBLE, `jz2nqqxhsckawd` DOUBLE, `jz2nqqxhsckbwd` DOUBLE, `jz2nqqxhsrkawd` DOUBLE, `jz2nqqxhsrkbwd` DOUBLE, `jz2kyqackyqwdsel` DOUBLE, `jz2kyqbckyqwdsel` DOUBLE, `jz2yfjackyqwd` DOUBLE, `jz2yfjbckyqwd` DOUBLE, `jz2trkyqwd` DOUBLE, `jz2trkyqwd1` DOUBLE, `jz2trkyqwd2` DOUBLE, `jz2trkyqwd3` DOUBLE, `jz2tckjyqwd1` DOUBLE, `jz2tckjyqwd2` DOUBLE, `jz2tckyqwd1` DOUBLE, `jz2bya` DOUBLE, `jz2byb` DOUBLE, `jz2pqwda` DOUBLE, `jz2pqwdb` DOUBLE, `jz2gmjadl` DOUBLE, `jz2gmjbdl` DOUBLE, `jz2gmjcdl` DOUBLE, `jz2gmjddl` DOUBLE, `jz2gmjedl` DOUBLE, `jz2gmjfdl` DOUBLE, `jz2yfjadl` DOUBLE, `jz2yfjbdl` DOUBLE, `jz2ycfjadl` DOUBLE, `jz2ycfjbdl` DOUBLE, `jz2sfjadl` DOUBLE, `jz2sfjbdl` DOUBLE, `jz2fdjyggl` DOUBLE, `jz2fdjwggl` DOUBLE, `jz2sjzs` DOUBLE, `jz2zfl` DOUBLE, `jz2ltyl` DOUBLE, `jz2smb` DOUBLE, `jz2rll` DOUBLE, `jz2grd` DOUBLE, `jz2zjwd` DOUBLE, `jz2yl` DOUBLE, `jz2kyqckwd` DOUBLE, `jz2abmfsybrkcy` DOUBLE, `jz2bbmfsybrkcy` DOUBLE, `jz2abjcsdmfytwdzdz` DOUBLE, `jz2bbjcsdmfytwdzdz` DOUBLE) TAGS (`iot_hub_id` VARCHAR(100), `device_group_code` VARCHAR(100), `device_code` VARCHAR(100))" + tdLog.info("stable ep_iot.sldc_dp created") + tdSql.execute(sql, queryTimes=1) + sql = "insert into ep_iot.sldc_dp_t1 using ep_iot.sldc_dp tags('a','a','a') values(now, now, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9,0,1);" + tdSql.execute(sql, queryTimes=1) + sql = "insert into ep_iot.sldc_dp_t1 using ep_iot.sldc_dp tags('b','b','b') values(now, now, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9,0,1);" + tdSql.execute(sql, queryTimes=1) + sql = "insert into ep_iot.sldc_dp_t1 using ep_iot.sldc_dp tags('c','c','c') values(now, now, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9,0,1);" + tdSql.execute(sql, queryTimes=1) + sql = "insert into ep_iot.sldc_dp_t1 using ep_iot.sldc_dp tags('d','d','d') values(now, now, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9,0,1);" + tdSql.execute(sql, queryTimes=1) + sql = "insert into ep_iot.sldc_dp_t1 using ep_iot.sldc_dp tags('e','e','e') values(now, now, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9,0,1);" + tdSql.execute(sql, queryTimes=1) + sql = "select scdw_code, scdw_name, jzmc, fdgl, jzzt from ((select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组1' as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组2' as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp)) where scdw_code like '%%';" + tdSql.query(sql, queryTimes=1) + tdSql.checkCols(5) + tdSql.checkRows(6) + + sql = "select scdw_name, scdw_code, jzmc, fdgl, jzzt from ((select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组1' as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组2' as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp)) where scdw_code like '%%';" + tdSql.query(sql, queryTimes=1) + tdSql.checkCols(5) + tdSql.checkRows(6) + sql = "select scdw_name, scdw_code, jzzt from ((select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组1' as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组2' as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp)) where scdw_code like '%%';" + tdSql.query(sql, queryTimes=1) + tdSql.checkRows(6) + tdSql.checkCols(3) + tdSql.execute("drop database ep_iot") + def run(self): tdSql.prepare() + self.test_TS_5630() tdLog.printNoPrefix("==========step1:create table") self.__create_tb() From 1c79d342cc587d62cc037a35e57fb865673ffac8 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Wed, 13 Nov 2024 17:59:29 +0800 Subject: [PATCH 09/60] fix: encode SVariablesInfo --- source/common/src/tmsg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index edf0db9954..e083176544 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -5618,6 +5618,7 @@ int32_t tEncodeSVariablesInfo(SEncoder *pEncoder, SVariablesInfo *pInfo) { TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->name)); TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->value)); TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->scope)); + TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->info)); return 0; } @@ -5625,6 +5626,7 @@ int32_t tDecodeSVariablesInfo(SDecoder *pDecoder, SVariablesInfo *pInfo) { TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->name)); TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->value)); TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->scope)); + TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->info)); return 0; } From 75c5209c8dea9ece4305407592cb446c43f6a064 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Wed, 13 Nov 2024 18:27:09 +0800 Subject: [PATCH 10/60] fix: SVariablesInfo compatibility --- source/common/src/tmsg.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index e083176544..bc8830505e 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -5618,7 +5618,6 @@ int32_t tEncodeSVariablesInfo(SEncoder *pEncoder, SVariablesInfo *pInfo) { TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->name)); TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->value)); TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->scope)); - TAOS_CHECK_RETURN(tEncodeCStr(pEncoder, pInfo->info)); return 0; } @@ -5626,7 +5625,6 @@ int32_t tDecodeSVariablesInfo(SDecoder *pDecoder, SVariablesInfo *pInfo) { TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->name)); TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->value)); TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->scope)); - TAOS_CHECK_RETURN(tDecodeCStrTo(pDecoder, pInfo->info)); return 0; } @@ -5644,6 +5642,12 @@ int32_t tSerializeSShowVariablesRsp(void *buf, int32_t bufLen, SShowVariablesRsp SVariablesInfo *pInfo = taosArrayGet(pRsp->variables, i); TAOS_CHECK_EXIT(tEncodeSVariablesInfo(&encoder, pInfo)); } + + for (int32_t i = 0; i < varNum; ++i) { + SVariablesInfo *pInfo = taosArrayGet(pRsp->variables, i); + TAOS_CHECK_RETURN(tEncodeCStr(&encoder, pInfo->info)); + } + tEndEncode(&encoder); _exit: @@ -5677,6 +5681,13 @@ int32_t tDeserializeSShowVariablesRsp(void *buf, int32_t bufLen, SShowVariablesR TAOS_CHECK_EXIT(terrno); } } + + if (!tDecodeIsEnd(&decoder)) { + for (int32_t i = 0; i < varNum; ++i) { + SVariablesInfo *pInfo = taosArrayGet(pRsp->variables, i); + TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, pInfo->info)); + } + } } tEndDecode(&decoder); From b64e28e6798a28778195b3b2b1799ad66fef3966 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 14 Nov 2024 09:19:58 +0800 Subject: [PATCH 11/60] docs: minor change --- .../zh/14-reference/01-components/01-taosd.md | 350 +++++++++--------- .../zh/14-reference/01-components/02-taosc.md | 141 ++++--- 2 files changed, 245 insertions(+), 246 deletions(-) diff --git a/docs/zh/14-reference/01-components/01-taosd.md b/docs/zh/14-reference/01-components/01-taosd.md index dc35d40b07..64ae69528b 100644 --- a/docs/zh/14-reference/01-components/01-taosd.md +++ b/docs/zh/14-reference/01-components/01-taosd.md @@ -27,65 +27,65 @@ taosd 命令行参数如下 ### 连接相关 |参数名称|支持版本|参数含义| -|-----------------------|-----------|-| -|firstEp | |taosd 启动时,主动连接的集群中首个 dnode 的 end point,默认值 localhost:6030| -|secondEp | |taosd 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,无默认值| -|fqdn | |taosd 监听的服务地址,默认为所在服务器上配置的第一个 hostname| -|serverPort | |taosd 监听的端口,默认值 6030| -|compressMsgSize | |是否对 RPC 消息进行压缩;-1:所有消息都不压缩;0:所有消息都压缩;N (N>0):只有大于 N 个字节的消息才压缩;默认值 -1| -|shellActivityTimer | |客户端向 mnode 发送心跳的时长,单位为秒,取值范围 1-120,默认值 3| -|numOfRpcSessions | |RPC 支持的最大连接数,取值范围 100-100000,默认值 30000| -|numOfRpcThreads | |RPC 线程数目,默认值为 CPU 核数的一半| -|numOfTaskQueueThreads | |dnode 处理 RPC 消息的线程数| -|statusInterval | |dnode 与 mnode 之间的心跳间隔| -|rpcQueueMemoryAllowed | |dnode 允许的 rpc 消息占用的内存最大值,单位 bytes,取值范围 104857600-INT64_MAX,默认值 服务器内存的 1/10 | -|resolveFQDNRetryTime | |FQDN 解析失败时的重试次数| -|timeToGetAvailableConn | |获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,默认值 500000| -|maxShellConns | |允许创建的最大链接数| -|maxRetryWaitTime | |重连最大超时时间| -|shareConnLimit |3.3.4.3 之后|内部参数,一个链接可以共享的查询数目,取值范围 1-256,默认值 10| -|readTimeout |3.3.4.3 之后|内部参数,最小超时时间,取值范围 64-604800,单位为秒,默认值 900| +|-----------------------|----------|-| +|firstEp | |taosd 启动时,主动连接的集群中首个 dnode 的 end point,默认值 localhost:6030| +|secondEp | |taosd 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,无默认值| +|fqdn | |taosd 监听的服务地址,默认为所在服务器上配置的第一个 hostname| +|serverPort | |taosd 监听的端口,默认值 6030| +|compressMsgSize | |是否对 RPC 消息进行压缩;-1:所有消息都不压缩;0:所有消息都压缩;N (N>0):只有大于 N 个字节的消息才压缩;默认值 -1| +|shellActivityTimer | |客户端向 mnode 发送心跳的时长,单位为秒,取值范围 1-120,默认值 3| +|numOfRpcSessions | |RPC 支持的最大连接数,取值范围 100-100000,默认值 30000| +|numOfRpcThreads | |RPC 线程数目,默认值为 CPU 核数的一半| +|numOfTaskQueueThreads | |dnode 处理 RPC 消息的线程数| +|statusInterval | |dnode 与 mnode 之间的心跳间隔| +|rpcQueueMemoryAllowed | |dnode 允许的 rpc 消息占用的内存最大值,单位 bytes,取值范围 104857600-INT64_MAX,默认值 服务器内存的 1/10 | +|resolveFQDNRetryTime | |FQDN 解析失败时的重试次数| +|timeToGetAvailableConn | |获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,默认值 500000| +|maxShellConns | |允许创建的最大链接数| +|maxRetryWaitTime | |重连最大超时时间| +|shareConnLimit |3.3.4.3 后|内部参数,一个链接可以共享的查询数目,取值范围 1-256,默认值 10| +|readTimeout |3.3.4.3 后|内部参数,最小超时时间,取值范围 64-604800,单位为秒,默认值 900| ### 监控相关 |参数名称|支持版本|参数含义| -|-----------------------|-----------|-| -|monitor | |是否收集监控数据并上报,0:关闭;1:打开;默认值 0| -|monitorFqdn | |taosKeeper 服务所在服务器的 FQDN,默认值 无| -|monitorPort | |taosKeeper 服务所监听的端口号,默认值 6043| -|monitorInterval | |监控数据库记录系统参数(CPU/内存)的时间间隔,单位是秒,取值范围 1-200000 ,默认值 30| -|monitorMaxLogs | |缓存的待上报日志条数| -|monitorComp | |是否采用压缩方式上报监控日志时| -|monitorLogProtocol | |是否打印监控日志| -|monitorForceV2 | |是否使用 V2 版本协议上报| -|telemetryReporting | |是否上传 telemetry,0:不上传,1:上传,默认值 1| -|telemetryServer | |telemetry 服务器地址| -|telemetryPort | |telemetry 服务器端口编号| -|telemetryInterval | |telemetry 上传时间间隔,单位为秒,默认 43200| -|crashReporting | |是否上传 crash 信息;0:不上传,1:上传;默认值 1| +|-----------------------|----------|-| +|monitor | |是否收集监控数据并上报,0:关闭;1:打开;默认值 0| +|monitorFqdn | |taosKeeper 服务所在服务器的 FQDN,默认值 无| +|monitorPort | |taosKeeper 服务所监听的端口号,默认值 6043| +|monitorInterval | |监控数据库记录系统参数(CPU/内存)的时间间隔,单位是秒,取值范围 1-200000 ,默认值 30| +|monitorMaxLogs | |缓存的待上报日志条数| +|monitorComp | |是否采用压缩方式上报监控日志时| +|monitorLogProtocol | |是否打印监控日志| +|monitorForceV2 | |是否使用 V2 版本协议上报| +|telemetryReporting | |是否上传 telemetry,0:不上传,1:上传,默认值 1| +|telemetryServer | |telemetry 服务器地址| +|telemetryPort | |telemetry 服务器端口编号| +|telemetryInterval | |telemetry 上传时间间隔,单位为秒,默认 43200| +|crashReporting | |是否上传 crash 信息;0:不上传,1:上传;默认值 1| ### 查询相关 |参数名称|支持版本|参数含义| -|------------------------|-----------|-| -|countAlwaysReturnValue | |count/hyperloglog 函数在输入数据为空或者 NULL 的情况下是否返回值;0:返回空行,1:返回;默认值 1;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了 TSMA 时,且相应的组或窗口内数据为空或者 NULL,对应的组或窗口将不返回查询结果;注意此参数客户端和服务端值应保持一致| -|tagFilterCache | |是否缓存标签过滤结果| -|maxNumOfDistinctRes | |允许返回的 distinct 结果最大行数,默认值 10 万,最大允许值 1 亿| -|queryBufferSize | |暂不生效| -|queryRspPolicy | |查询响应策略| -|filterScalarMode | |强制使用标量过滤模式,0:关闭;1:开启,默认值 0| -|queryPlannerTrace | |内部参数,查询计划是否输出详细日志| -|queryNodeChunkSize | |内部参数,查询计划的块大小| -|queryUseNodeAllocator | |内部参数,查询计划的分配方法| -|queryMaxConcurrentTables| |内部参数,查询计划的并发数目| -|queryRsmaTolerance | |内部参数,用于判定查询哪一级 rsma 数据时的容忍时间,单位为毫秒| -|enableQueryHb | |内部参数,是否发送查询心跳消息| -|pqSortMemThreshold | |内部参数,排序使用的内存阈值| +|------------------------|----------|-| +|countAlwaysReturnValue | |count/hyperloglog 函数在输入数据为空或者 NULL 的情况下是否返回值;0:返回空行,1:返回;默认值 1;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了 TSMA 时,且相应的组或窗口内数据为空或者 NULL,对应的组或窗口将不返回查询结果;注意此参数客户端和服务端值应保持一致| +|tagFilterCache | |是否缓存标签过滤结果| +|maxNumOfDistinctRes | |允许返回的 distinct 结果最大行数,默认值 10 万,最大允许值 1 亿| +|queryBufferSize | |暂不生效| +|queryRspPolicy | |查询响应策略| +|filterScalarMode | |强制使用标量过滤模式,0:关闭;1:开启,默认值 0| +|queryPlannerTrace | |内部参数,查询计划是否输出详细日志| +|queryNodeChunkSize | |内部参数,查询计划的块大小| +|queryUseNodeAllocator | |内部参数,查询计划的分配方法| +|queryMaxConcurrentTables| |内部参数,查询计划的并发数目| +|queryRsmaTolerance | |内部参数,用于判定查询哪一级 rsma 数据时的容忍时间,单位为毫秒| +|enableQueryHb | |内部参数,是否发送查询心跳消息| +|pqSortMemThreshold | |内部参数,排序使用的内存阈值| ### 区域相关 |参数名称|支持版本|参数含义| -|-----------------|-----------|-| -|timezone | |时区;缺省从系统中动态获取当前的时区设置| -|locale | |系统区位信息及编码格式,缺省从系统中获取| -|charset | |字符集编码,缺省从系统中获取| +|-----------------|----------|-| +|timezone | |时区;缺省从系统中动态获取当前的时区设置| +|locale | |系统区位信息及编码格式,缺省从系统中获取| +|charset | |字符集编码,缺省从系统中获取| :::info 1. 为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix 时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。 @@ -164,147 +164,147 @@ charset 的有效值是 UTF-8。 ### 存储相关 |参数名称|支持版本|参数含义| -|--------------------|-----------|-| -|dataDir | |数据文件目录,所有的数据文件都将写入该目录,默认值 /var/lib/taos| -|tempDir | |指定所有系统运行过程中的临时文件生成的目录,默认值 /tmp| -|minimalDataDirGB | |dataDir 指定的时序数据存储目录所需要保留的最小空间,单位 GB,默认值 2| -|minimalTmpDirGB | |tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,默认值 1| -|minDiskFreeSize |3.1.1.0 之后|当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件,单位为字节,取值范围 52428800-1073741824,默认值为 52428800;企业版参数| -|s3MigrateIntervalSec|3.3.4.3 之后|本地数据文件自动上传 S3 的触发周期,单位为秒。最小值:600;最大值:100000。默认值 3600;企业版参数| -|s3MigrateEnabled |3.3.4.3 之后|是否自动进行 S3 迁移,默认值为 0,表示关闭自动 S3 迁移,可配置为 1;企业版参数| -|s3Accesskey |3.3.4.3 之后|冒号分隔的用户 SecretId:SecretKey,例如 AKIDsQmwsfKxTo2A6nGVXZN0UlofKn6JRRSJ:lIdoy99ygEacU7iHfogaN2Xq0yumSm1E;企业版参数| -|s3Endpoint |3.3.4.3 之后|用户所在地域的 COS 服务域名,支持 http 和 https,bucket 的区域需要与 endpoint 保持一致,否则无法访问;企业版参数| -|s3BucketName |3.3.4.3 之后|存储桶名称,减号后面是用户注册 COS 服务的 AppId,其中 AppId 是 COS 特有,AWS 和阿里云都没有,配置时需要作为 bucket name 的一部分,使用减号分隔;参数值均为字符串类型,但不需要引号;例如 test0711-1309024725;企业版参数| -|s3PageCacheSize |3.3.4.3 之后|S3 page cache 缓存页数目,取值范围 4-1048576,单位为页,默认值 4096;企业版参数| -|s3UploadDelaySec |3.3.4.3 之后|data 文件持续多长时间不再变动后上传至 S3,取值范围 1-2592000 (30天),单位为秒,默认值 60;企业版参数| -|cacheLazyLoadThreshold | |内部参数,缓存的装载策略| +|--------------------|----------|-| +|dataDir | |数据文件目录,所有的数据文件都将写入该目录,默认值 /var/lib/taos| +|tempDir | |指定所有系统运行过程中的临时文件生成的目录,默认值 /tmp| +|minimalDataDirGB | |dataDir 指定的时序数据存储目录所需要保留的最小空间,单位 GB,默认值 2| +|minimalTmpDirGB | |tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,默认值 1| +|minDiskFreeSize |3.1.1.0 后|当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件,单位为字节,取值范围 52428800-1073741824,默认值为 52428800;企业版参数| +|s3MigrateIntervalSec|3.3.4.3 后|本地数据文件自动上传 S3 的触发周期,单位为秒。最小值:600;最大值:100000。默认值 3600;企业版参数| +|s3MigrateEnabled |3.3.4.3 后|是否自动进行 S3 迁移,默认值为 0,表示关闭自动 S3 迁移,可配置为 1;企业版参数| +|s3Accesskey |3.3.4.3 后|冒号分隔的用户 SecretId:SecretKey,例如 AKIDsQmwsfKxTo2A6nGVXZN0UlofKn6JRRSJ:lIdoy99ygEacU7iHfogaN2Xq0yumSm1E;企业版参数| +|s3Endpoint |3.3.4.3 后|用户所在地域的 COS 服务域名,支持 http 和 https,bucket 的区域需要与 endpoint 保持一致,否则无法访问;企业版参数| +|s3BucketName |3.3.4.3 后|存储桶名称,减号后面是用户注册 COS 服务的 AppId,其中 AppId 是 COS 特有,AWS 和阿里云都没有,配置时需要作为 bucket name 的一部分,使用减号分隔;参数值均为字符串类型,但不需要引号;例如 test0711-1309024725;企业版参数| +|s3PageCacheSize |3.3.4.3 后|S3 page cache 缓存页数目,取值范围 4-1048576,单位为页,默认值 4096;企业版参数| +|s3UploadDelaySec |3.3.4.3 后|data 文件持续多长时间不再变动后上传至 S3,取值范围 1-2592000 (30天),单位为秒,默认值 60;企业版参数| +|cacheLazyLoadThreshold| |内部参数,缓存的装载策略| ### 集群相关 |参数名称|支持版本|参数含义| -|--------------------------|-----------|-| -|supportVnodes | |dnode 支持的最大 vnode 数目,取值范围 0-4096,默认值 CPU 核数的 2 倍 + 5| -|numOfCommitThreads | |落盘线程的最大数量,取值范围 0-1024,默认值为 4| -|numOfMnodeReadThreads | |mnode 的 Read 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)| -|numOfVnodeQueryThreads | |vnode 的 Query 线程数目,取值范围 0-1024,默认值为 CPU 核数的两倍(不超过 16)| -|numOfVnodeFetchThreads | |vnode 的 Fetch 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)| -|numOfVnodeRsmaThreads | |vnode 的 Rsma 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)| -|numOfQnodeQueryThreads | |qnode 的 Query 线程数目,取值范围 0-1024,默认值为 CPU 核数的两倍(不超过 16)| -|numOfSnodeSharedThreads | |snode 的共享线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不小于 2,不超过 4)| -|numOfSnodeUniqueThreads | |snode 的独占线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不小于 2,不超过 4)| -|ratioOfVnodeStreamThreads | |流计算使用 vnode 线程的比例,取值范围 0.01-4,默认值 4| -|ttlUnit | |ttl 参数的单位,取值范围 1-31572500,单位为秒,默认值 86400| -|ttlPushInterval | |ttl 检测超时频率,取值范围 1-100000,单位为秒,默认值 10| -|ttlChangeOnWrite | |ttl 到期时间是否伴随表的修改操作改变;0:不改变,1:改变;默认值为 0| -|ttlBatchDropNum | |ttl 一批删除子表的数目,最小值为 0,默认值 10000| -|retentionSpeedLimitMB | |数据在不同级别硬盘上迁移时的速度限制,取值范围 0-1024,单位 MB,默认值 0,表示不限制| -|maxTsmaNum | |集群内可创建的TSMA个数;取值范围 0-3;默认值 3| -|tmqMaxTopicNum | |订阅最多可建立的 topic 数量;取值范围 1-10000;默认值为 20| -|tmqRowSize | |订阅数据块的最大记录条数,取值范围 1-1000000,默认值 4096| -|audit | |审计功能开关;企业版参数| -|auditInterval | |审计数据上报的时间间隔;企业版参数| -|auditCreateTable | |是否针对创建子表开启申计功能;企业版参数| -|encryptAlgorithm | |数据加密算法;企业版参数| -|encryptScope | |加密范围;企业版参数| -|enableWhiteList | |白名单功能开关;企业版参数| -|syncLogBufferMemoryAllowed| |一个 dnode 允许的 sync 日志缓存消息占用的内存最大值,单位 bytes,取值范围 104857600-INT64_MAX,默认值 服务器内存的 1/10,3.1.3.2/3.3.2.13 版本开始生效 | -|syncElectInterval | |内部参数,用于同步模块调试| -|syncHeartbeatInterval | |内部参数,用于同步模块调试| -|syncHeartbeatTimeout | |内部参数,用于同步模块调试| -|syncSnapReplMaxWaitN | |内部参数,用于同步模块调试| -|syncSnapReplMaxWaitN | |内部参数,用于同步模块调试| -|arbHeartBeatIntervalSec | |内部参数,用于同步模块调试| -|arbCheckSyncIntervalSec | |内部参数,用于同步模块调试| -|arbSetAssignedTimeoutSec | |内部参数,用于同步模块调试| -|mndSdbWriteDelta | |内部参数,用于 mnode 模块调试| -|mndLogRetention | |内部参数,用于 mnode 模块调试| -|skipGrant | |内部参数,用于授权检查| -|trimVDbIntervalSec | |内部参数,用于删除过期数据| -|ttlFlushThreshold | |内部参数,ttl 定时器的频率| -|compactPullupInterval | |内部参数,数据重整定时器的频率| -|walFsyncDataSizeLimit | |内部参数,WAL 进行 FSYNC 的阈值| -|transPullupInterval | |内部参数,mnode 执行事务的重试间隔| -|mqRebalanceInterval | |内部参数,消费者再平衡的时间间隔| -|uptimeInterval | |内部参数,用于记录系统启动时间| -|timeseriesThreshold | |内部参数,用于统计用量| -|udf | |是否启动 UDF 服务;0:不启动,1:启动;默认值为 0 | -|udfdResFuncs | |内部参数,用于 UDF 结果集设置| -|udfdLdLibPath | |内部参数,表示 UDF 装载的库路径| +|--------------------------|----------|-| +|supportVnodes | |dnode 支持的最大 vnode 数目,取值范围 0-4096,默认值 CPU 核数的 2 倍 + 5| +|numOfCommitThreads | |落盘线程的最大数量,取值范围 0-1024,默认值为 4| +|numOfMnodeReadThreads | |mnode 的 Read 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)| +|numOfVnodeQueryThreads | |vnode 的 Query 线程数目,取值范围 0-1024,默认值为 CPU 核数的两倍(不超过 16)| +|numOfVnodeFetchThreads | |vnode 的 Fetch 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)| +|numOfVnodeRsmaThreads | |vnode 的 Rsma 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)| +|numOfQnodeQueryThreads | |qnode 的 Query 线程数目,取值范围 0-1024,默认值为 CPU 核数的两倍(不超过 16)| +|numOfSnodeSharedThreads | |snode 的共享线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不小于 2,不超过 4)| +|numOfSnodeUniqueThreads | |snode 的独占线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不小于 2,不超过 4)| +|ratioOfVnodeStreamThreads | |流计算使用 vnode 线程的比例,取值范围 0.01-4,默认值 4| +|ttlUnit | |ttl 参数的单位,取值范围 1-31572500,单位为秒,默认值 86400| +|ttlPushInterval | |ttl 检测超时频率,取值范围 1-100000,单位为秒,默认值 10| +|ttlChangeOnWrite | |ttl 到期时间是否伴随表的修改操作改变;0:不改变,1:改变;默认值为 0| +|ttlBatchDropNum | |ttl 一批删除子表的数目,最小值为 0,默认值 10000| +|retentionSpeedLimitMB | |数据在不同级别硬盘上迁移时的速度限制,取值范围 0-1024,单位 MB,默认值 0,表示不限制| +|maxTsmaNum | |集群内可创建的TSMA个数;取值范围 0-3;默认值 3| +|tmqMaxTopicNum | |订阅最多可建立的 topic 数量;取值范围 1-10000;默认值为 20| +|tmqRowSize | |订阅数据块的最大记录条数,取值范围 1-1000000,默认值 4096| +|audit | |审计功能开关;企业版参数| +|auditInterval | |审计数据上报的时间间隔;企业版参数| +|auditCreateTable | |是否针对创建子表开启申计功能;企业版参数| +|encryptAlgorithm | |数据加密算法;企业版参数| +|encryptScope | |加密范围;企业版参数| +|enableWhiteList | |白名单功能开关;企业版参数| +|syncLogBufferMemoryAllowed| |一个 dnode 允许的 sync 日志缓存消息占用的内存最大值,单位 bytes,取值范围 104857600-INT64_MAX,默认值 服务器内存的 1/10,3.1.3.2/3.3.2.13 版本开始生效 | +|syncElectInterval | |内部参数,用于同步模块调试| +|syncHeartbeatInterval | |内部参数,用于同步模块调试| +|syncHeartbeatTimeout | |内部参数,用于同步模块调试| +|syncSnapReplMaxWaitN | |内部参数,用于同步模块调试| +|syncSnapReplMaxWaitN | |内部参数,用于同步模块调试| +|arbHeartBeatIntervalSec | |内部参数,用于同步模块调试| +|arbCheckSyncIntervalSec | |内部参数,用于同步模块调试| +|arbSetAssignedTimeoutSec | |内部参数,用于同步模块调试| +|mndSdbWriteDelta | |内部参数,用于 mnode 模块调试| +|mndLogRetention | |内部参数,用于 mnode 模块调试| +|skipGrant | |内部参数,用于授权检查| +|trimVDbIntervalSec | |内部参数,用于删除过期数据| +|ttlFlushThreshold | |内部参数,ttl 定时器的频率| +|compactPullupInterval | |内部参数,数据重整定时器的频率| +|walFsyncDataSizeLimit | |内部参数,WAL 进行 FSYNC 的阈值| +|transPullupInterval | |内部参数,mnode 执行事务的重试间隔| +|mqRebalanceInterval | |内部参数,消费者再平衡的时间间隔| +|uptimeInterval | |内部参数,用于记录系统启动时间| +|timeseriesThreshold | |内部参数,用于统计用量| +|udf | |是否启动 UDF 服务;0:不启动,1:启动;默认值为 0 | +|udfdResFuncs | |内部参数,用于 UDF 结果集设置| +|udfdLdLibPath | |内部参数,表示 UDF 装载的库路径| ### 流计算参数 |参数名称|支持版本|参数含义| -|-----------------------|-----------|-| -|disableStream | |流计算的启动开关| -|streamBufferSize | |控制内存中窗口状态缓存的大小,默认值为 128MB| -|streamAggCnt | |内部参数,并发进行聚合计算的数目| -|checkpointInterval | |内部参数,checkponit 同步间隔| -|concurrentCheckpoint | |内部参数,是否并发检查 checkpoint| -|maxStreamBackendCache | |内部参数,流计算使用的最大缓存| -|streamSinkDataRate | |内部参数,用于控制流计算结果的写入速度| +|-----------------------|----------|-| +|disableStream | |流计算的启动开关| +|streamBufferSize | |控制内存中窗口状态缓存的大小,默认值为 128MB| +|streamAggCnt | |内部参数,并发进行聚合计算的数目| +|checkpointInterval | |内部参数,checkponit 同步间隔| +|concurrentCheckpoint | |内部参数,是否并发检查 checkpoint| +|maxStreamBackendCache | |内部参数,流计算使用的最大缓存| +|streamSinkDataRate | |内部参数,用于控制流计算结果的写入速度| ### 日志相关 |参数名称|支持版本|参数含义| -|----------------|-----------|-| -|logDir | |日志文件目录,运行日志将写入该目录,默认值 /var/log/taos| -|minimalLogDirGB | |日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位 GB,默认值 1| -|numOfLogLines | |单个日志文件允许的最大行数,默认值 10,000,000| -|asyncLog | |日志写入模式,0:同步,1:异步,默认值 1| -|logKeepDays | |日志文件的最长保存时间,单位:天,默认值 0,意味着无限保存,日志文件不会被重命名,也不会有新的日志文件滚动产生,但日志文件的内容有可能会不断滚动,取决于日志文件大小的设置;当设置为大于 0 的值时,当日志文件大小达到设置的上限时会被重命名为 taosdlog.yyy,其中 yyy 为日志文件最后修改的时间戳,并滚动产生新的日志文件| -|slowLogThreshold|3.3.3.0 之后|慢查询门限值,大于等于门限值认为是慢查询,单位秒,默认值 3 | -|slowLogMaxLen |3.3.3.0 之后|慢查询日志最大长度,取值范围 1-16384,默认值 4096| -|slowLogScope |3.3.3.0 之后|慢查询记录类型,取值范围 ALL/QUERY/INSERT/OTHERS/NONE,默认值 QUERY| -|slowLogExceptDb |3.3.3.0 之后|指定的数据库不上报慢查询,仅支持配置换一个数据库| -|debugFlag | |运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志);默认值 131 或 135 (取决于不同模块)| -|tmrDebugFlag | |定时器模块的日志开关,取值范围同上| -|uDebugFlag | |共用功能模块的日志开关,取值范围同上| -|rpcDebugFlag | |rpc 模块的日志开关,取值范围同上| -|qDebugFlag | |query 模块的日志开关,取值范围同上| -|dDebugFlag | |dnode 模块的日志开关,取值范围同上| -|vDebugFlag | |vnode 模块的日志开关,取值范围同上| -|mDebugFlag | |mnode 模块的日志开关,取值范围同上| -|azDebugFlag |3.3.4.3 之后|S3 模块的日志开关,取值范围同上| -|sDebugFlag | |sync 模块的日志开关,取值范围同上| -|tsdbDebugFlag | |tsdb 模块的日志开关,取值范围同上| -|tqDebugFlag | |tq 模块的日志开关,取值范围同上| -|fsDebugFlag | |fs 模块的日志开关,取值范围同上| -|udfDebugFlag | |udf 模块的日志开关,取值范围同上| -|smaDebugFlag | |sma 模块的日志开关,取值范围同上| -|idxDebugFlag | |index 模块的日志开关,取值范围同上| -|tdbDebugFlag | |tdb 模块的日志开关,取值范围同上| -|metaDebugFlag | |meta 模块的日志开关,取值范围同上| -|stDebugFlag | |stream 模块的日志开关,取值范围同上| -|sndDebugFlag | |snode 模块的日志开关,取值范围同上| +|----------------|----------|-| +|logDir | |日志文件目录,运行日志将写入该目录,默认值 /var/log/taos| +|minimalLogDirGB | |日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位 GB,默认值 1| +|numOfLogLines | |单个日志文件允许的最大行数,默认值 10,000,000| +|asyncLog | |日志写入模式,0:同步,1:异步,默认值 1| +|logKeepDays | |日志文件的最长保存时间,单位:天,默认值 0,意味着无限保存,日志文件不会被重命名,也不会有新的日志文件滚动产生,但日志文件的内容有可能会不断滚动,取决于日志文件大小的设置;当设置为大于 0 的值时,当日志文件大小达到设置的上限时会被重命名为 taosdlog.yyy,其中 yyy 为日志文件最后修改的时间戳,并滚动产生新的日志文件| +|slowLogThreshold|3.3.3.0 后|慢查询门限值,大于等于门限值认为是慢查询,单位秒,默认值 3 | +|slowLogMaxLen |3.3.3.0 后|慢查询日志最大长度,取值范围 1-16384,默认值 4096| +|slowLogScope |3.3.3.0 后|慢查询记录类型,取值范围 ALL/QUERY/INSERT/OTHERS/NONE,默认值 QUERY| +|slowLogExceptDb |3.3.3.0 后|指定的数据库不上报慢查询,仅支持配置换一个数据库| +|debugFlag | |运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志);默认值 131 或 135 (取决于不同模块)| +|tmrDebugFlag | |定时器模块的日志开关,取值范围同上| +|uDebugFlag | |共用功能模块的日志开关,取值范围同上| +|rpcDebugFlag | |rpc 模块的日志开关,取值范围同上| +|qDebugFlag | |query 模块的日志开关,取值范围同上| +|dDebugFlag | |dnode 模块的日志开关,取值范围同上| +|vDebugFlag | |vnode 模块的日志开关,取值范围同上| +|mDebugFlag | |mnode 模块的日志开关,取值范围同上| +|azDebugFlag |3.3.4.3 后|S3 模块的日志开关,取值范围同上| +|sDebugFlag | |sync 模块的日志开关,取值范围同上| +|tsdbDebugFlag | |tsdb 模块的日志开关,取值范围同上| +|tqDebugFlag | |tq 模块的日志开关,取值范围同上| +|fsDebugFlag | |fs 模块的日志开关,取值范围同上| +|udfDebugFlag | |udf 模块的日志开关,取值范围同上| +|smaDebugFlag | |sma 模块的日志开关,取值范围同上| +|idxDebugFlag | |index 模块的日志开关,取值范围同上| +|tdbDebugFlag | |tdb 模块的日志开关,取值范围同上| +|metaDebugFlag | |meta 模块的日志开关,取值范围同上| +|stDebugFlag | |stream 模块的日志开关,取值范围同上| +|sndDebugFlag | |snode 模块的日志开关,取值范围同上| ### 调试相关 |参数名称|支持版本|参数含义| -|--------------------|-----------|-| -|enableCoreFile | |crash 时是否生成 core 文件,0:不生成,1:生成;默认值 1| -|configDir | |配置文件所在目录| -|scriptDir | |内部测试工具的脚本目录| -|assert | |断言控制开关,默认值 0| -|randErrorChance | |内部参数,用于随机失败测试| -|randErrorDivisor | |内部参数,用于随机失败测试| -|randErrorScope | |内部参数,用于随机失败测试| -|safetyCheckLevel | |内部参数,用于随机失败测试| -|experimental | |内部参数,用于一些实验特性| -|simdEnable |3.3.4.3 之后|内部参数,用于测试 SIMD 加速| -|AVX512Enable |3.3.4.3 之后|内部参数,用于测试 AVX512 加速| -|rsyncPort | |内部参数,用于调试流计算| -|snodeAddress | |内部参数,用于调试流计算| -|checkpointBackupDir | |内部参数,用于恢复 snode 数据| -|enableAuditDelete | |内部参数,用于测试审计功能| -|slowLogThresholdTest| |内部参数,用于测试慢日志| +|--------------------|----------|-| +|enableCoreFile | |crash 时是否生成 core 文件,0:不生成,1:生成;默认值 1| +|configDir | |配置文件所在目录| +|scriptDir | |内部测试工具的脚本目录| +|assert | |断言控制开关,默认值 0| +|randErrorChance | |内部参数,用于随机失败测试| +|randErrorDivisor | |内部参数,用于随机失败测试| +|randErrorScope | |内部参数,用于随机失败测试| +|safetyCheckLevel | |内部参数,用于随机失败测试| +|experimental | |内部参数,用于一些实验特性| +|simdEnable |3.3.4.3 后|内部参数,用于测试 SIMD 加速| +|AVX512Enable |3.3.4.3 后|内部参数,用于测试 AVX512 加速| +|rsyncPort | |内部参数,用于调试流计算| +|snodeAddress | |内部参数,用于调试流计算| +|checkpointBackupDir | |内部参数,用于恢复 snode 数据| +|enableAuditDelete | |内部参数,用于测试审计功能| +|slowLogThresholdTest| |内部参数,用于测试慢日志| ### 压缩参数 |参数名称|支持版本|参数含义| -|------------|-----------|-| -|fPrecision | |设置 float 类型浮点数压缩精度 ,取值范围 0.1 ~ 0.00000001 ,默认值 0.00000001 , 小于此值的浮点数尾数部分将被截断| -|dPrecision | |设置 double 类型浮点数压缩精度 , 取值范围 0.1 ~ 0.0000000000000001 , 默认值 0.0000000000000001 , 小于此值的浮点数尾数部分将被截取| -|lossyColumn |3.3.0.0 之前|对 float 和/或 double 类型启用 TSZ 有损压缩;取值范围 float/double/none;默认值 none,表示关闭无损压缩| -|ifAdtFse | |在启用 TSZ 有损压缩时,使用 FSE 算法替换 HUFFMAN 算法,FSE 算法压缩速度更快,但解压稍慢,追求压缩速度可选用此算法;0:关闭,1:打开;默认值为 0| -|maxRange | |内部参数,用于有损压缩设置| -|curRange | |内部参数,用于有损压缩设置| -|compressor | |内部参数,用于有损压缩设置| +|------------|----------|-| +|fPrecision | |设置 float 类型浮点数压缩精度 ,取值范围 0.1 ~ 0.00000001 ,默认值 0.00000001 , 小于此值的浮点数尾数部分将被截断| +|dPrecision | |设置 double 类型浮点数压缩精度 , 取值范围 0.1 ~ 0.0000000000000001 , 默认值 0.0000000000000001 , 小于此值的浮点数尾数部分将被截取| +|lossyColumn |3.3.0.0 前|对 float 和/或 double 类型启用 TSZ 有损压缩;取值范围 float/double/none;默认值 none,表示关闭无损压缩| +|ifAdtFse | |在启用 TSZ 有损压缩时,使用 FSE 算法替换 HUFFMAN 算法,FSE 算法压缩速度更快,但解压稍慢,追求压缩速度可选用此算法;0:关闭,1:打开;默认值为 0| +|maxRange | |内部参数,用于有损压缩设置| +|curRange | |内部参数,用于有损压缩设置| +|compressor | |内部参数,用于有损压缩设置| **补充说明** 1. 在 3.2.0.0 ~ 3.3.0.0(不包含)版本生效,启用该参数后不能回退到升级前的版本 diff --git a/docs/zh/14-reference/01-components/02-taosc.md b/docs/zh/14-reference/01-components/02-taosc.md index 3efaddee26..09653ae3ef 100755 --- a/docs/zh/14-reference/01-components/02-taosc.md +++ b/docs/zh/14-reference/01-components/02-taosc.md @@ -10,99 +10,98 @@ TDengine 客户端驱动提供了应用编程所需要的全部 API,并且在 ### 连接相关 |参数名称|支持版本|参数含义| -|----------------------|-----------|-| -|firstEp | |启动时,主动连接的集群中首个 dnode 的 endpoint,缺省值:hostname:6030,若无法获取该服务器的 hostname,则赋值为 localhost| -|secondEp | |启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,没有缺省值| -|compressMsgSize | |是否对 RPC 消息进行压缩;-1:所有消息都不压缩;0:所有消息都压缩;N (N>0):只有大于 N 个字节的消息才压缩;缺省值 -1| -|shellActivityTimer | |客户端向 mnode 发送心跳的时长,单位为秒,取值范围 1-120,默认值 3| -|numOfRpcSessions | |RPC 支持的最大连接数,取值范围 100-100000,缺省值 30000| -|numOfRpcThreads | |RPC 线程数目,默认值为 CPU 核数的一半| -|timeToGetAvailableConn| |获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,缺省值 500000| -|useAdapter | |内部参数,是否使用 taosadapter,影响 CSV 文件导入| -|shareConnLimit |3.3.4.3 之后|内部参数,一个链接可以共享的查询数目,取值范围 1-256,默认值 10| -|readTimeout |3.3.4.3 之后|内部参数,最小超时时间,取值范围 64-604800,单位为秒,默认值 900| +|----------------------|----------|-| +|firstEp | |启动时,主动连接的集群中首个 dnode 的 endpoint,缺省值:hostname:6030,若无法获取该服务器的 hostname,则赋值为 localhost| +|secondEp | |启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,没有缺省值| +|compressMsgSize | |是否对 RPC 消息进行压缩;-1:所有消息都不压缩;0:所有消息都压缩;N (N>0):只有大于 N 个字节的消息才压缩;缺省值 -1| +|shellActivityTimer | |客户端向 mnode 发送心跳的时长,单位为秒,取值范围 1-120,默认值 3| +|numOfRpcSessions | |RPC 支持的最大连接数,取值范围 100-100000,缺省值 30000| +|numOfRpcThreads | |RPC 线程数目,默认值为 CPU 核数的一半| +|timeToGetAvailableConn| |获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,缺省值 500000| +|useAdapter | |内部参数,是否使用 taosadapter,影响 CSV 文件导入| +|shareConnLimit |3.3.4.3 后|内部参数,一个链接可以共享的查询数目,取值范围 1-256,默认值 10| +|readTimeout |3.3.4.3 后|内部参数,最小超时时间,取值范围 64-604800,单位为秒,默认值 900| ### 查询相关 |参数名称|支持版本|参数含义| -|---------------------------------|-----------|-| -|countAlwaysReturnValue | |count/hyperloglog 函数在输入数据为空或者 NULL 的情况下是否返回值;0:返回空行,1:返回;默认值 1;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了 TSMA 时,且相应的组或窗口内数据为空或者 NULL,对应的组或窗口将不返回查询结果;注意此参数客户端和服务端值应保持一致| -|keepColumnName | |Last、First、LastRow 函数查询且未指定别名时,自动设置别名为列名(不含函数名),因此 order by 子句如果引用了该列名将自动引用该列对应的函数;1:表示自动设置别名为列名(不包含函数名),0:表示不自动设置别名;缺省值:0| -|multiResultFunctionStarReturnTags|3.3.3.0 以后|查询超级表时,last(\*)/last_row(\*)/first(\*) 是否返回标签列;查询普通表、子表时,不受该参数影响;0:不返回标签列,1:返回标签列;缺省值:0;该参数设置为 0 时,last(\*)/last_row(\*)/first(\*) 只返回超级表的普通列;为 1 时,返回超级表的普通列和标签列| -| - | |指定单个客户端元数据缓存大小的最大值,单位 MB;缺省值 -1,表示无限制| -|maxTsmaCalcDelay | |查询时客户端可允许的 tsma 计算延迟,若 tsma 的计算延迟大于配置值,则该 TSMA 将不会被使用;取值范围 600s - 86400s,即 10 分钟 - 1 小时;缺省值:600 秒| -|tsmaDataDeleteMark | |TSMA 计算的历史数据中间结果保存时间,单位为毫秒;取值范围 >= 3600000,即大于等于1h;缺省值:86400000,即 1d | -|queryPolicy | |查询语句的执行策略,1:只使用 vnode,不使用 qnode;2:没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行;3:vnode 只运行扫描算子,其余算子均在 qnode 执行;缺省值:1| -|queryTableNotExistAsEmpty | |查询表不存在时是否返回空结果集;false:返回错误;true:返回空结果集;缺省值 false| -|querySmaOptimize | |sma index 的优化策略,0:表示不使用 sma index,永远从原始数据进行查询;1:表示使用 sma index,对符合的语句,直接从预计算的结果进行查询;缺省值:0| -|queryPlannerTrace | |内部参数,查询计划是否输出详细日志| -|queryNodeChunkSize | |内部参数,查询计划的块大小| -|queryUseNodeAllocator | |内部参数,查询计划的分配方法| -|queryMaxConcurrentTables | |内部参数,查询计划的并发数目| -|enableQueryHb | |内部参数,是否发送查询心跳消息| -|minSlidingTime | |内部参数,sliding 的最小允许值| -|minIntervalTime | |内部参数,interval 的最小允许值| +|---------------------------------|---------|-| +|countAlwaysReturnValue | |count/hyperloglog 函数在输入数据为空或者 NULL 的情况下是否返回值;0:返回空行,1:返回;默认值 1;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了 TSMA 时,且相应的组或窗口内数据为空或者 NULL,对应的组或窗口将不返回查询结果;注意此参数客户端和服务端值应保持一致| +|keepColumnName | |Last、First、LastRow 函数查询且未指定别名时,自动设置别名为列名(不含函数名),因此 order by 子句如果引用了该列名将自动引用该列对应的函数;1:表示自动设置别名为列名(不包含函数名),0:表示不自动设置别名;缺省值:0| +|multiResultFunctionStarReturnTags|3.3.3.0 后|查询超级表时,last(\*)/last_row(\*)/first(\*) 是否返回标签列;查询普通表、子表时,不受该参数影响;0:不返回标签列,1:返回标签列;缺省值:0;该参数设置为 0 时,last(\*)/last_row(\*)/first(\*) 只返回超级表的普通列;为 1 时,返回超级表的普通列和标签列| +|metaCacheMaxSize | |指定单个客户端元数据缓存大小的最大值,单位 MB;缺省值 -1,表示无限制| +|maxTsmaCalcDelay | |查询时客户端可允许的 tsma 计算延迟,若 tsma 的计算延迟大于配置值,则该 TSMA 将不会被使用;取值范围 600s - 86400s,即 10 分钟 - 1 小时;缺省值:600 秒| +|tsmaDataDeleteMark | |TSMA 计算的历史数据中间结果保存时间,单位为毫秒;取值范围 >= 3600000,即大于等于1h;缺省值:86400000,即 1d | +|queryPolicy | |查询语句的执行策略,1:只使用 vnode,不使用 qnode;2:没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行;3:vnode 只运行扫描算子,其余算子均在 qnode 执行;缺省值:1| +|queryTableNotExistAsEmpty | |查询表不存在时是否返回空结果集;false:返回错误;true:返回空结果集;缺省值 false| +|querySmaOptimize | |sma index 的优化策略,0:表示不使用 sma index,永远从原始数据进行查询;1:表示使用 sma index,对符合的语句,直接从预计算的结果进行查询;缺省值:0| +|queryPlannerTrace | |内部参数,查询计划是否输出详细日志| +|queryNodeChunkSize | |内部参数,查询计划的块大小| +|queryUseNodeAllocator | |内部参数,查询计划的分配方法| +|queryMaxConcurrentTables | |内部参数,查询计划的并发数目| +|enableQueryHb | |内部参数,是否发送查询心跳消息| +|minSlidingTime | |内部参数,sliding 的最小允许值| +|minIntervalTime | |内部参数,interval 的最小允许值| ### 写入相关 |参数名称|支持版本|参数含义| -|------------------------------|-----------|-| -|smlChildTableName | |schemaless 自定义的子表名的 key,无缺省值| -|smlAutoChildTableNameDelimiter| |schemaless tag 之间的连接符,连起来作为子表名,无缺省值| -|smlTagName | |schemaless tag 为空时默认的 tag 名字,缺省值 "_tag_null"| -|smlTsDefaultName | |schemaless 自动建表的时间列名字通过该配置设置,缺省值 "_ts"| -|smlDot2Underline | |schemaless 把超级表名中的 dot 转成下划线| -|maxInsertBatchRows | |内部参数,一批写入的最大条数| +|------------------------------|----------|-| +|smlChildTableName | |schemaless 自定义的子表名的 key,无缺省值| +|smlAutoChildTableNameDelimiter| |schemaless tag 之间的连接符,连起来作为子表名,无缺省值| +|smlTagName | |schemaless tag 为空时默认的 tag 名字,缺省值 "_tag_null"| +|smlTsDefaultName | |schemaless 自动建表的时间列名字通过该配置设置,缺省值 "_ts"| +|smlDot2Underline | |schemaless 把超级表名中的 dot 转成下划线| +|maxInsertBatchRows | |内部参数,一批写入的最大条数| ### 区域相关 |参数名称|支持版本|参数含义| -|-----------------|-----------|-| -|timezone | |时区;缺省从系统中动态获取当前的时区设置| -|locale | |系统区位信息及编码格式,缺省从系统中获取| -|charset | |字符集编码,缺省从系统中获取| +|-----------------|----------|-| +|timezone | |时区;缺省从系统中动态获取当前的时区设置| +|locale | |系统区位信息及编码格式,缺省从系统中获取| +|charset | |字符集编码,缺省从系统中获取| ### 存储相关 |参数名称|支持版本|参数含义| -|-----------------|-----------|-| -|tempDir | |指定所有运行过程中的临时文件生成的目录,Linux 平台默认值为 /tmp| -|minimalTmpDirGB | |tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,缺省值:1| +|-----------------|----------|-| +|tempDir | |指定所有运行过程中的临时文件生成的目录,Linux 平台默认值为 /tmp| +|minimalTmpDirGB | |tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,缺省值:1| ### 日志相关 |参数名称|支持版本|参数含义| -|-----------------|-----------|-| -|logDir | |日志文件目录,运行日志将写入该目录,缺省值:/var/log/taos| -|minimalLogDirGB | |日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位 GB,缺省值:1| -|numOfLogLines | |单个日志文件允许的最大行数,缺省值:10,000,000| -|asyncLog | |日志写入模式,0:同步,1:异步,缺省值:1| -|logKeepDays | |日志文件的最长保存时间,单位:天,缺省值:0,意味着无限保存,日志文件不会被重命名,也不会有新的日志文件滚动产生,但日志文件的内容有可能会不断滚动,取决于日志文件大小的设置;当设置为大于 0 的值时,当日志文件大小达到设置的上限时会被重命名为 taoslogx.yyy,其中 yyy 为日志文件最后修改的时间戳,并滚动产生新的日志文件| -|debugFlag | |运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志);默认值 131 或 135 (取决于不同模块)| -|tmrDebugFlag | |定时器模块的日志开关,取值范围同上| -|uDebugFlag | |共用功能模块的日志开关,取值范围同上| -|rpcDebugFlag | |rpc 模块的日志开关,取值范围同上| -|jniDebugFlag | |jni 模块的日志开关,取值范围同上| -|qDebugFlag | |query 模块的日志开关,取值范围同上| -|cDebugFlag | |客户端模块的日志开关,取值范围同上| -|simDebugFlag | |内部参数,测试工具的日志开关,取值范围同上| -|tqClientDebugFlag|3.3.4.3 之后|客户端模块的日志开关,取值范围同上| +|-----------------|----------|-| +|logDir | |日志文件目录,运行日志将写入该目录,缺省值:/var/log/taos| +|minimalLogDirGB | |日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位 GB,缺省值:1| +|numOfLogLines | |单个日志文件允许的最大行数,缺省值:10,000,000| +|asyncLog | |日志写入模式,0:同步,1:异步,缺省值:1| +|logKeepDays | |日志文件的最长保存时间,单位:天,缺省值:0,意味着无限保存,日志文件不会被重命名,也不会有新的日志文件滚动产生,但日志文件的内容有可能会不断滚动,取决于日志文件大小的设置;当设置为大于 0 的值时,当日志文件大小达到设置的上限时会被重命名为 taoslogx.yyy,其中 yyy 为日志文件最后修改的时间戳,并滚动产生新的日志文件| +|debugFlag | |运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志);默认值 131 或 135 (取决于不同模块)| +|tmrDebugFlag | |定时器模块的日志开关,取值范围同上| +|uDebugFlag | |共用功能模块的日志开关,取值范围同上| +|rpcDebugFlag | |rpc 模块的日志开关,取值范围同上| +|jniDebugFlag | |jni 模块的日志开关,取值范围同上| +|qDebugFlag | |query 模块的日志开关,取值范围同上| +|cDebugFlag | |客户端模块的日志开关,取值范围同上| +|simDebugFlag | |内部参数,测试工具的日志开关,取值范围同上| +|tqClientDebugFlag|3.3.4.3 后|客户端模块的日志开关,取值范围同上| ### 调试相关 |参数名称|支持版本|参数含义| |-----------------|-----------|-| -|crashReporting | |是否上传 crash 到 telemetry,0:不上传,1:上传;缺省值:1| -|enableCoreFile | |crash 时是否生成 core 文件,0:不生成,1:生成;缺省值:1| -|assert | |断言控制开关,缺省值:0| -|configDir | |配置文件所在目录| -|scriptDir | |内部参数,测试用例的目录| -|randErrorChance |3.3.3.0 之后|内部参数,用于随机失败测试| -|randErrorDivisor |3.3.3.0 之后|内部参数,用于随机失败测试| -|randErrorScope |3.3.3.0 之后|内部参数,用于随机失败测试| -|safetyCheckLevel |3.3.3.0 之后|内部参数,用于随机失败测试| -|simdEnable |3.3.4.3 之后|内部参数,用于测试 SIMD 加速| -|AVX512Enable |3.3.4.3 之后|内部参数,用于测试 AVX512 加速| +|crashReporting | |是否上传 crash 到 telemetry,0:不上传,1:上传;缺省值:1| +|enableCoreFile | |crash 时是否生成 core 文件,0:不生成,1:生成;缺省值:1| +|assert | |断言控制开关,缺省值:0| +|configDir | |配置文件所在目录| +|scriptDir | |内部参数,测试用例的目录| +|randErrorChance |3.3.3.0 后|内部参数,用于随机失败测试| +|randErrorDivisor |3.3.3.0 后|内部参数,用于随机失败测试| +|randErrorScope |3.3.3.0 后|内部参数,用于随机失败测试| +|safetyCheckLevel |3.3.3.0 后|内部参数,用于随机失败测试| +|simdEnable |3.3.4.3 后|内部参数,用于测试 SIMD 加速| +|AVX512Enable |3.3.4.3 后|内部参数,用于测试 AVX512 加速| ### SHELL 相关 |参数名称|支持版本|参数含义| -|-----------------|-----------|-| -|enableScience | |是否开启科学计数法显示浮点数;0:不开始,1:开启;缺省值:1| +|-----------------|----------|-| +|enableScience | |是否开启科学计数法显示浮点数;0:不开始,1:开启;缺省值:1| ## API From 75a7da81792d5cc51b5a84622987dc167a704563 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Thu, 14 Nov 2024 09:36:39 +0800 Subject: [PATCH 12/60] fix: ci issue --- source/common/src/tmisce.c | 2 +- tests/system-test/0-others/information_schema.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/common/src/tmisce.c b/source/common/src/tmisce.c index dfba2ebf6c..8988fab56a 100644 --- a/source/common/src/tmisce.c +++ b/source/common/src/tmisce.c @@ -331,7 +331,7 @@ _start: TAOS_CHECK_GOTO(colDataSetVal(pColInfo, numOfRows, scope, false), NULL, _exit); char info[TSDB_CONFIG_INFO_LEN + VARSTR_HEADER_SIZE] = {0}; - if (strcasecmp(pItem->name, "dataDir") == 0) { + if (strcasecmp(pItem->name, "dataDir") == 0 && pDiskCfg) { char* buf = &info[VARSTR_HEADER_SIZE]; valueLen = tsnprintf(buf, TSDB_CONFIG_INFO_LEN, "level %d primary %d disabled %" PRIi8, pDiskCfg->level, pDiskCfg->primary, pDiskCfg->disable); diff --git a/tests/system-test/0-others/information_schema.py b/tests/system-test/0-others/information_schema.py index aa548d4e59..ccf95db563 100644 --- a/tests/system-test/0-others/information_schema.py +++ b/tests/system-test/0-others/information_schema.py @@ -222,7 +222,7 @@ class TDTestCase: tdSql.query("select * from information_schema.ins_columns where db_name ='information_schema'") tdLog.info(len(tdSql.queryResult)) - tdSql.checkEqual(True, len(tdSql.queryResult) in range(281, 282)) + tdSql.checkEqual(True, len(tdSql.queryResult) in range(282, 283)) tdSql.query("select * from information_schema.ins_columns where db_name ='performance_schema'") tdSql.checkEqual(56, len(tdSql.queryResult)) From 05a3c7bbcde0bc43377b9a10ae780c8b6582e97b Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Thu, 14 Nov 2024 09:37:15 +0800 Subject: [PATCH 13/60] doc(arch/last): new section for last/last_row cache --- docs/zh/26-tdinternal/01-arch.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/zh/26-tdinternal/01-arch.md b/docs/zh/26-tdinternal/01-arch.md index 8aa69e45d5..7091ca9661 100644 --- a/docs/zh/26-tdinternal/01-arch.md +++ b/docs/zh/26-tdinternal/01-arch.md @@ -293,6 +293,14 @@ TDengine 采纳了一种独特的时间驱动缓存管理策略,亦称为写 此外,考虑到物联网数据的特点,用户通常最关注的是数据的实时性,即最新产生的数据。TDengine 很好地利用了这一特点,优先将最新到达的(即当前状态)数据存储在缓存中。具体而言,TDengine 会将最新到达的数据直接存入缓存,以便快速响应用户对最新一条或多条数据的查询和分析需求,从而在整体上提高数据库查询的响应速度。从这个角度来看,通过合理设置数据库参数,TDengine 完全可以作为数据缓存来使用,这样就无须再部署 Redis 或其他额外的缓存系统。这种做法不仅有效简化了系统架构,还有助于降低运维成本。需要注意的是,一旦 TDengine 重启,缓存中的数据将被清除,所有先前缓存的数据都会被批量写入硬盘,而不会像专业的 Key-Value 缓存系统那样自动将之前缓存的数据重新加载回缓存。 +### last/last_row 缓存 + +在时序数据的场景中,查询表的最后一条记录(last_row)或最后一条非 NULL 记录(last)是一个常见的需求。为了提高 TDengine 对这种查询的响应速度,TSDB 为每张表的 last 和 last_row 数据提供了 LRU 缓存。LRU 缓存采用延迟加载策略,当首次查询某张表的 last 或 last_row 时,缓存模块会去内存池和磁盘文件加载数据,处理后放入LRU 缓存,并返回给查询模块继续处理;当有新的数据插入或删除时,如果缓存需要更新,会进行相应的更新操作;如果缓存中没有当前被写入表的数据,则直接跳过,无需其它操作。 + +此外在缓存配置更新的时候,也会更新缓存数据。比如,缓存功能默认是关闭的,用户使用命令开启缓存功能之后,就会在首次查询时加载数据;当关闭缓存开关时,会释放之前的缓存区。当查询某一个子表的 last 或 last_row 数据时,如果缓存中没有,则从内存池和磁盘文件加载对应的 last 或 last_row 数据到缓存中;当查询某一个超级表的 last 或 last_row 数据时,这个超级表对应的所有子表都需要加载到缓存中。 + +通过数据库参数 cachemodel 可以配置某一个数据库的缓存参数,默认值为 "none",表示不开启缓存,另外三个值为 "last_row","last_value","both";分别是开启 last_row 缓存,开启 last 缓存,和两个同时开启。缓存当前所使用的内存数量,可在通过 show vgroups; 命令,在 cacheload 列中进行查看,单位为字节。 + ### 持久化存储 TDengine 采用了一种数据驱动的策略来实现缓存数据的持久化存储。当 vnode 中的缓存数据积累到一定量时,为了避免阻塞后续数据的写入,TDengine 会启动落盘线程,将这些缓存数据写入持久化存储设备。在此过程中,TDengine 会创建新的数据库日志文件用于数据落盘,并在落盘成功后删除旧的日志文件,以防止日志文件无限制增长。 From ab7b0026b36d757f07ce083d02e6e5e4b6d6d77f Mon Sep 17 00:00:00 2001 From: wangjiaming0909 <604227650@qq.com> Date: Thu, 14 Nov 2024 10:19:44 +0800 Subject: [PATCH 14/60] refine code --- source/libs/planner/src/planOptimizer.c | 43 ++++++++++++++++--------- tests/system-test/2-query/union.py | 7 +++- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index b179c58ee1..39024731ed 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -3501,15 +3501,17 @@ static int32_t eliminateProjOptFindProjPrefixWithOrderCheck(SProjectLogicNode* p *orderMatch = false; break; } - SNode* pNew = NULL; - code = nodesCloneNode(pChildTarget, &pNew); - if (TSDB_CODE_SUCCESS == code) { - code = nodesListMakeStrictAppend(pNewChildTargets, pNew); - } - if (TSDB_CODE_SUCCESS != code && pNewChildTargets) { - nodesDestroyList(*pNewChildTargets); - *pNewChildTargets = NULL; - break; + if (pNewChildTargets) { + SNode* pNew = NULL; + code = nodesCloneNode(pChildTarget, &pNew); + if (TSDB_CODE_SUCCESS == code) { + code = nodesListMakeStrictAppend(pNewChildTargets, pNew); + } + if (TSDB_CODE_SUCCESS != code && pNewChildTargets) { + nodesDestroyList(*pNewChildTargets); + *pNewChildTargets = NULL; + break; + } } } return code; @@ -3543,6 +3545,8 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* int32_t code = 0; bool isSetOpProj = false; bool orderMatch = false; + bool sizeMatch = LIST_LENGTH(pProjectNode->pProjections) == LIST_LENGTH(pChild->pTargets); + bool needReplaceTargets = true; if (NULL == pProjectNode->node.pParent) { SNodeList* pNewChildTargets = NULL; @@ -3553,7 +3557,12 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* // For sql: select ... from (select ... union all select ...); // When eliminating the outer proj (the outer select), we have to make sure that the outer proj projections and // union all project targets have same columns in the same order. See detail in TD-30188 - code = eliminateProjOptFindProjPrefixWithOrderCheck(pProjectNode, (SProjectLogicNode*)pChild, &pNewChildTargets, &orderMatch); + code = eliminateProjOptFindProjPrefixWithOrderCheck(pProjectNode, (SProjectLogicNode*)pChild, + sizeMatch ? NULL : &pNewChildTargets, &orderMatch); + if (TSDB_CODE_SUCCESS == code && sizeMatch && orderMatch) { + pNewChildTargets = pChild->pTargets; + needReplaceTargets = false; + } } else { FOREACH(pProjection, pProjectNode->pProjections) { FOREACH(pChildTarget, pChild->pTargets) { @@ -3577,10 +3586,12 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* } if (eliminateProjOptCanChildConditionUseChildTargets(pChild, pNewChildTargets) && (!isSetOpProj || orderMatch)) { - nodesDestroyList(pChild->pTargets); - pChild->pTargets = pNewChildTargets; + if (needReplaceTargets) { + nodesDestroyList(pChild->pTargets); + pChild->pTargets = pNewChildTargets; + } } else { - nodesDestroyList(pNewChildTargets); + if (needReplaceTargets) nodesDestroyList(pNewChildTargets); OPTIMIZE_FLAG_SET_MASK(pProjectNode->node.optimizedFlag, OPTIMIZE_FLAG_ELIMINATE_PROJ); pCxt->optimized = true; return TSDB_CODE_SUCCESS; @@ -3603,10 +3614,10 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* NODES_CLEAR_LIST(pProjectNode->node.pChildren); nodesDestroyNode((SNode*)pProjectNode); // if pChild is a project logic node, remove its projection which is not reference by its target. - alignProjectionWithTarget(pChild); - if (isSetOpProj && orderMatch) { + if (needReplaceTargets) { + alignProjectionWithTarget(pChild); // Since we have eliminated the outer proj, we need to push down the new targets to the children of the set operation. - code = eliminateProjOptPushTargetsToSetOpChildren((SProjectLogicNode*)pChild); + if (isSetOpProj && orderMatch && !sizeMatch) code = eliminateProjOptPushTargetsToSetOpChildren((SProjectLogicNode*)pChild); } } pCxt->optimized = true; diff --git a/tests/system-test/2-query/union.py b/tests/system-test/2-query/union.py index b74db0104d..5104489592 100644 --- a/tests/system-test/2-query/union.py +++ b/tests/system-test/2-query/union.py @@ -399,7 +399,12 @@ class TDTestCase: tdSql.query(sql, queryTimes=1) tdSql.checkRows(6) tdSql.checkCols(3) - tdSql.execute("drop database ep_iot") + + sql = "select scdw_code, scdw_name, jzmc, fdgl, jzzt,ts from ((select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组1' as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01072016' as scdw_code, '盛鲁电厂' as scdw_name, '机组2' as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '00103673' as scdw_code, '鲁西电厂' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt, last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组1'as jzmc, last(jz1fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp) union all ( select '01061584' as scdw_code, '富源热电' as scdw_name, '机组2'as jzmc, last(jz2fdjyggl) as fdgl, '填报' as jzzt ,last(ts) as ts from ep_iot.sldc_dp)) where scdw_code like '%%';" + tdSql.query(sql, queryTimes=1) + tdSql.checkCols(6) + tdSql.checkRows(6) + ##tdSql.execute("drop database ep_iot") def run(self): tdSql.prepare() From bc7d46a5101bf3848341b5310f9b18ce9b210b44 Mon Sep 17 00:00:00 2001 From: haoranchen Date: Thu, 14 Nov 2024 16:57:04 +0800 Subject: [PATCH 15/60] Update index.md --- docs/zh/28-releases/03-notes/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/zh/28-releases/03-notes/index.md b/docs/zh/28-releases/03-notes/index.md index 3268c088b2..d1a48ab9a8 100644 --- a/docs/zh/28-releases/03-notes/index.md +++ b/docs/zh/28-releases/03-notes/index.md @@ -3,6 +3,7 @@ title: 版本说明 sidebar_label: 版本说明 description: 各版本版本说明 --- -[3.3.4.3](./3.3.4.3) + +[3.3.4.3](./3.3.4.3) [3.3.3.0](./3.3.3.0) [3.3.2.0](./3.3.2.0) From 15e4b2dec360314bfd41922827d1ab78e643e2b3 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 14 Nov 2024 17:07:33 +0800 Subject: [PATCH 16/60] Update 02-anomaly-detection.md --- .../06-TDgpt/05-anomaly-detection/02-anomaly-detection.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md b/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md index 469e75c1fd..dcd46488da 100644 --- a/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md +++ b/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md @@ -1,6 +1,6 @@ --- -title: "异常检测算法" -sidebar_label: "异常检测算法" +title: "检测算法" +sidebar_label: "检测算法" --- 本节介绍内置异常检测算法模型的定义和使用方法。 From 3309e7b536cfadf4ad0f10228bd6c05efc1b97af Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 14 Nov 2024 17:14:42 +0800 Subject: [PATCH 17/60] fix: adjust bucket to 40 and exit drop db --- tests/army/storage/s3/s3Basic.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/army/storage/s3/s3Basic.py b/tests/army/storage/s3/s3Basic.py index 273a6129e1..cefd4ef60d 100644 --- a/tests/army/storage/s3/s3Basic.py +++ b/tests/army/storage/s3/s3Basic.py @@ -47,7 +47,7 @@ for test: class TDTestCase(TBase): - index = eutil.cpuRand(20) + 1 + index = eutil.cpuRand(40) + 1 bucketName = f"ci-bucket{index}" updatecfgDict = { "supportVnodes":"1000", @@ -63,6 +63,10 @@ class TDTestCase(TBase): tdLog.info(f"assign bucketName is {bucketName}\n") maxFileSize = (128 + 10) * 1014 * 1024 # add 10M buffer + def exit(self, log): + self.dropDb(True) + tdLog.exit(log) + def insertData(self): tdLog.info(f"insert data.") # taosBenchmark run @@ -107,8 +111,8 @@ class TDTestCase(TBase): loop = 0 rets = [] overCnt = 0 - while loop < 200: - time.sleep(3) + while loop < 150: + time.sleep(2) # check upload to s3 rets = eos.runRetList(cmd) @@ -134,7 +138,7 @@ class TDTestCase(TBase): # check can pass if overCnt > 0: - tdLog.exit(f"s3 have {overCnt} files over size.") + self.exit(f"s3 have {overCnt} files over size.") def doAction(self): @@ -159,7 +163,7 @@ class TDTestCase(TBase): return True time.sleep(1) - tdLog.exit(f"stream count is not expect . expect = 100000 or 100001 real={count} . sql={sql}") + self.exit(f"stream count is not expect . expect = 100000 or 100001 real={count} . sql={sql}") def checkCreateDb(self, keepLocal, chunkSize, compact): From 9257ba77ede8fd00d77085a252db38354d6ced84 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 14 Nov 2024 17:34:51 +0800 Subject: [PATCH 18/60] Update 02-anomaly-detection.md --- .../06-TDgpt/05-anomaly-detection/02-anomaly-detection.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md b/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md index dcd46488da..be66aa7053 100644 --- a/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md +++ b/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md @@ -18,19 +18,19 @@ sidebar_label: "检测算法" |k|标准差倍数|选填|3| -- IQR[2]:四分位距 (Interquartile range, IQR) 是一种衡量变异性的方法. 四分位数将一个按等级排序的数据集划分为四个相等的部分。即 Q1(第 1 个四分位数)、Q2(第 2 个四分位数)和 Q3(第 3 个四分位数)。IQR 定义为 $Q3–Q1$,位于 $Q3+1.5$。无输入参数。 +- IQR[2]:Interquartile range(IQR),四分位距是一种衡量变异性的方法。四分位数将一个按等级排序的数据集划分为四个相等的部分。即 Q1(第 1 个四分位数)、Q2(第 2 个四分位数)和 Q3(第 3 个四分位数)。 $IQR=Q3-Q1$,对于 $v$, $Q1-(1.5 \times IQR) \le v \le Q3+(1.5 \times IQR)$ 是正常值,范围之外的是异常值。无输入参数。 -- Grubbs[3]: 又称为 Grubbs' test,即最大标准残差测试。Grubbs 通常用作检验最大值、最小值偏离均值的程度是否为异常,该单变量数据集遵循近似标准正态分布。非正态分布数据集不能使用该方法。无输入参数。 +- Grubbs[3]: Grubbs' test,即最大标准残差测试。Grubbs 通常用作检验最大值、最小值偏离均值的程度是否为异常,该单变量数据集遵循近似标准正态分布。非正态分布数据集不能使用该方法。无输入参数。 - SHESD[4]: 带有季节性的 ESD 检测算法。ESD 可以检测时间序列数据的多异常点。需要指定异常点比例的上界***k***,最差的情况是至多 49.9%。数据集的异常比例一般不超过 5% |参数|说明|是否必选|默认值| |---|---|---|---| -|k|异常点在输入数据集中占比,范围是 $1\le K \le 49.9$ |选填|5| +|k|异常点在输入数据集中占比 $1 \le K \le 49.9$ |选填|5| ### 基于数据密度的检测方法 -LOF[5]: 局部离群因子(LOF,又叫局部异常因子)算法是 Breunig 于 2000 年提出的一种基于密度的局部离群点检测算法,该方法适用于不同类簇密度分散情况迥异的数据。根据数据点周围的数据密集情况,首先计算每个数据点的一个局部可达密度,然后通过局部可达密度进一步计算得到每个数据点的一个离群因子,该离群因子即标识了一个数据点的离群程度,因子值越大,表示离群程度越高,因子值越小,表示离群程度越低。最后,输出离群程度最大的 $top(n)$ 个点。 +LOF[5]: Local Outlier Factor(LOF),局部离群因子/局部异常因子,是 Breunig 在 2000 年提出的一种基于密度的局部离群点检测算法,该方法适用于不同类簇密度分散情况迥异的数据。根据数据点周围的数据密集情况,首先计算每个数据点的一个局部可达密度,然后通过局部可达密度进一步计算得到每个数据点的一个离群因子,该离群因子即标识了一个数据点的离群程度,因子值越大,表示离群程度越高,因子值越小,表示离群程度越低。最后,输出离群程度最大的 $topK$ 个点。 ### 基于自编码器的检测方法 From ae32d4bb7ef616d60f4edb228c9450c3066e34b9 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 14 Nov 2024 17:35:38 +0800 Subject: [PATCH 19/60] Update 02-anomaly-detection.md --- .../06-TDgpt/05-anomaly-detection/02-anomaly-detection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md b/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md index be66aa7053..42ab04ad44 100644 --- a/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md +++ b/docs/zh/06-advanced/06-TDgpt/05-anomaly-detection/02-anomaly-detection.md @@ -20,7 +20,7 @@ sidebar_label: "检测算法" - IQR[2]:Interquartile range(IQR),四分位距是一种衡量变异性的方法。四分位数将一个按等级排序的数据集划分为四个相等的部分。即 Q1(第 1 个四分位数)、Q2(第 2 个四分位数)和 Q3(第 3 个四分位数)。 $IQR=Q3-Q1$,对于 $v$, $Q1-(1.5 \times IQR) \le v \le Q3+(1.5 \times IQR)$ 是正常值,范围之外的是异常值。无输入参数。 -- Grubbs[3]: Grubbs' test,即最大标准残差测试。Grubbs 通常用作检验最大值、最小值偏离均值的程度是否为异常,该单变量数据集遵循近似标准正态分布。非正态分布数据集不能使用该方法。无输入参数。 +- Grubbs[3]: Grubbs' test,即最大标准残差测试。Grubbs 通常用作检验最大值、最小值偏离均值的程度是否为异常,要求单变量数据集遵循近似标准正态分布。非正态分布数据集不能使用该方法。无输入参数。 - SHESD[4]: 带有季节性的 ESD 检测算法。ESD 可以检测时间序列数据的多异常点。需要指定异常点比例的上界***k***,最差的情况是至多 49.9%。数据集的异常比例一般不超过 5% From 6a8d1e3cf2ce4b4e541cc4181cad4cf0054d3f9c Mon Sep 17 00:00:00 2001 From: Yu Chen <74105241+yu285@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:41:56 +0800 Subject: [PATCH 20/60] docs:fix a typo 03-table.md --- docs/zh/14-reference/03-taos-sql/03-table.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/14-reference/03-taos-sql/03-table.md b/docs/zh/14-reference/03-taos-sql/03-table.md index 81ad60e3d2..40e2802fcd 100644 --- a/docs/zh/14-reference/03-taos-sql/03-table.md +++ b/docs/zh/14-reference/03-taos-sql/03-table.md @@ -227,7 +227,7 @@ DROP TABLE [IF EXISTS] [db_name.]tb_name [, [IF EXISTS] [db_name.]tb_name] ... 如下 SQL 语句可以列出当前数据库中的所有表名。 ```sql -SHOW TABLES [LIKE tb_name_wildchar]; +SHOW TABLES [LIKE tb_name_wildcard]; ``` ### 显示表创建语句 From 37021cb6f6d0aa1d69120c66bafd8492df4795b9 Mon Sep 17 00:00:00 2001 From: Yu Chen <74105241+yu285@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:56:22 +0800 Subject: [PATCH 21/60] docs: Optimize description of JDBC subscription.md --- docs/zh/07-develop/07-tmq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/07-develop/07-tmq.md b/docs/zh/07-develop/07-tmq.md index a91a764c67..8b272bdfff 100644 --- a/docs/zh/07-develop/07-tmq.md +++ b/docs/zh/07-develop/07-tmq.md @@ -16,7 +16,7 @@ TDengine 提供了类似于消息队列产品的数据订阅和消费接口。 **注意** 在 TDengine 连接器实现中,对于订阅查询,有以下限制。 -- 查询语句限制:订阅查询只能使用 select 语句,不支持其他类型的SQL,如 insert、update 或 delete 等。 +- 查询语句限制:订阅查询只能使用 select 语句,并不支持其他类型的SQL,如订阅库,订阅超级表(非 select 方式),insert、update 或 delete 等。 - 原始始数据查询:订阅查询只能查询原始数据,而不能查询聚合或计算结果。 - 时间顺序限制:订阅查询只能按照时间正序查询数据。 From 3b9e7aaf137bbcfd035f3ef18099452508cce018 Mon Sep 17 00:00:00 2001 From: yingzhao Date: Thu, 14 Nov 2024 16:41:04 +0800 Subject: [PATCH 22/60] docs(database): add arch diagram for property keep --- .../14-reference/03-taos-sql/02-database.md | 16 ++++++----- docs/zh/14-reference/03-taos-sql/05-insert.md | 27 ++++++++++++------ .../03-taos-sql/pic/database-keep.jpg | Bin 0 -> 116011 bytes 3 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 docs/zh/14-reference/03-taos-sql/pic/database-keep.jpg 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 4f799bdde9..f1847dda5c 100644 --- a/docs/zh/14-reference/03-taos-sql/02-database.md +++ b/docs/zh/14-reference/03-taos-sql/02-database.md @@ -43,7 +43,7 @@ database_option: { - VGROUPS:数据库中初始 vgroup 的数目。 - PRECISION:数据库的时间戳精度。ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认 ms 毫秒。 -- REPLICA:表示数据库副本数,取值为 1、2 或 3,默认为 1; 2 仅在企业版 3.3.0.0 及以后版本中可用。在集群中使用,副本数必须小于或等于 DNODE 的数目。且使用时存在以下限制: +- REPLICA:表示数据库副本数,取值为 1、2 或 3,默认为 1; 2 仅在企业版 3.3.0.0 及以后版本中可用。在集群中使用,副本数必须小于或等于 DNODE 的数目。且使用时存在以下限制: - 暂不支持对双副本数据库相关 Vgroup 进行 SPLITE VGROUP 或 REDISTRIBUTE VGROUP 操作 - 单副本数据库可变更为双副本数据库,但不支持从双副本变更为其它副本数,也不支持从三副本变更为双副本 - BUFFER: 一个 VNODE 写入内存池大小,单位为 MB,默认为 256,最小为 3,最大为 16384。 @@ -63,7 +63,8 @@ database_option: { - DURATION:数据文件存储数据的时间跨度。可以使用加单位的表示形式,如 DURATION 100h、DURATION 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。不加时间单位时默认单位为天,如 DURATION 50 表示 50 天。 - 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 会取最大的保存时间)。 +- 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 会取最大的保存时间)。了解更多,请点击 [关于主键时间戳](https://docs.taosdata.com/reference/taos-sql/insert/#%E5%85%B3%E4%BA%8E%E4%B8%BB%E9%94%AE%E6%97%B6%E9%97%B4%E6%88%B3)。 + - STT_TRIGGER:表示落盘文件触发文件合并的个数。开源版本固定为 1,企业版本可设置范围为 1 到 16。对于少表高频写入场景,此参数建议使用默认配置;而对于多表低频写入场景,此参数建议配置较大的值。 - SINGLE_STABLE:表示此数据库中是否只可以创建一个超级表,用于超级表列非常多的情况。 - 0:表示可以创建多张超级表。 @@ -78,6 +79,7 @@ database_option: { - WAL_FSYNC_PERIOD:当 WAL_LEVEL 参数设置为 2 时,用于设置落盘的周期。默认为 3000,单位毫秒。最小为 0,表示每次写入立即落盘;最大为 180000,即三分钟。 - WAL_RETENTION_PERIOD: 为了数据订阅消费,需要 WAL 日志文件额外保留的最大时长策略。WAL 日志清理,不受订阅客户端消费状态影响。单位为 s。默认为 3600,表示在 WAL 保留最近 3600 秒的数据,请根据数据订阅的需要修改这个参数为适当值。 - WAL_RETENTION_SIZE:为了数据订阅消费,需要 WAL 日志文件额外保留的最大累计大小策略。单位为 KB。默认为 0,表示累计大小无上限。 + ### 创建数据库示例 ```sql @@ -88,7 +90,7 @@ create database if not exists db vgroups 10 buffer 10 ### 使用数据库 -``` +```sql USE db_name; ``` @@ -96,7 +98,7 @@ USE db_name; ## 删除数据库 -``` +```sql DROP DATABASE [IF EXISTS] db_name ``` @@ -126,7 +128,7 @@ alter_database_option: { } ``` -### 修改 CACHESIZE +### 修改 CACHESIZE 修改数据库参数的命令使用简单,难的是如何确定是否需要修改以及如何修改。本小节描述如何判断数据库的 cachesize 是否够用。 @@ -155,13 +157,13 @@ alter_database_option: { ### 查看系统中的所有数据库 -``` +```sql SHOW DATABASES; ``` ### 显示一个数据库的创建语句 -``` +```sql SHOW CREATE DATABASE db_name \G; ``` diff --git a/docs/zh/14-reference/03-taos-sql/05-insert.md b/docs/zh/14-reference/03-taos-sql/05-insert.md index 40f8e95006..ccf24e882c 100644 --- a/docs/zh/14-reference/03-taos-sql/05-insert.md +++ b/docs/zh/14-reference/03-taos-sql/05-insert.md @@ -5,9 +5,11 @@ description: 写入数据的详细语法 --- ## 写入语法 + 写入记录支持两种语法, 正常语法和超级表语法. 正常语法下, 紧跟INSERT INTO后名的表名是子表名或者普通表名. 超级表语法下, 紧跟INSERT INTO后名的表名是超级表名 ### 正常语法 + ```sql INSERT INTO tb_name @@ -22,7 +24,9 @@ INSERT INTO INSERT INTO tb_name [(field1_name, ...)] subquery ``` + ### 超级表语法 + ```sql INSERT INTO stb1_name [(field1_name, ...)] @@ -32,16 +36,18 @@ INSERT INTO ...]; ``` -**关于时间戳** +#### 关于主键时间戳 -1. TDengine 要求插入的数据必须要有时间戳,插入数据的时间戳要注意以下几点: +TDengine 要求插入的数据必须要有时间戳,插入数据的时间戳要注意以下几点: -2. 时间戳不同的格式语法会有不同的精度影响。字符串格式的时间戳写法不受所在 DATABASE 的时间精度设置影响;而长整形格式的时间戳写法会受到所在 DATABASE 的时间精度设置影响。例如,时间戳"2021-07-13 16:16:48"的 UNIX 秒数为 1626164208。则其在毫秒精度下需要写作 1626164208000,在微秒精度设置下就需要写为 1626164208000000,纳秒精度设置下需要写为 1626164208000000000。 +1. 时间戳不同的格式语法会有不同的精度影响。字符串格式的时间戳写法不受所在 DATABASE 的时间精度设置影响;而长整形格式的时间戳写法会受到所在 DATABASE 的时间精度设置影响。例如,时间戳"2021-07-13 16:16:48"的 UNIX 秒数为 1626164208。则其在毫秒精度下需要写作 1626164208000,在微秒精度设置下就需要写为 1626164208000000,纳秒精度设置下需要写为 1626164208000000000。 -3. 一次插入多行数据时,不要把首列的时间戳的值都写 NOW。否则会导致语句中的多条记录使用相同的时间戳,于是就可能出现相互覆盖以致这些数据行无法全部被正确保存。其原因在于,NOW 函数在执行中会被解析为所在 SQL 语句的客户端执行时间,出现在同一语句中的多个 NOW 标记也就会被替换为完全相同的时间戳取值。 - 允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值(数据保留的天数, 可以在创建数据库时指定,缺省值是 3650 天)。允许插入的最新记录的时间戳,取决于数据库的 PRECISION 值(时间戳精度, 可以在创建数据库时指定, ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认毫秒):如果是毫秒或微秒, 取值为 1970 年 1 月 1 日 00:00:00.000 UTC 加上 1000 年, 即 2970 年 1 月 1 日 00:00:00.000 UTC; 如果是纳秒, 取值为 1970 年 1 月 1 日 00:00:00.000000000 UTC 加上 292 年, 即 2262 年 1 月 1 日 00:00:00.000000000 UTC。 +2. 一次插入多行数据时,不要把首列的时间戳的值都写 NOW。否则会导致语句中的多条记录使用相同的时间戳,于是就可能出现相互覆盖以致这些数据行无法全部被正确保存。其原因在于,NOW 函数在执行中会被解析为所在 SQL 语句的客户端执行时间,出现在同一语句中的多个 NOW 标记也就会被替换为完全相同的时间戳取值。 -**语法说明** +3. 允许插入的最大时间戳为当前时间加上 100 年, 比如当前时间为`2024-11-11 12:00:00`,则允许插入的最大时间戳为`2124-11-11 12:00:00`。允许插入的最小时间戳取决于数据库的 KEEP 设置。企业版支持三级存储,可以设置多个 KEEP 时间,如下图所示,如果数据库的 KEEP 配置为`100h,100d,3650d`,则允许的最小时间戳为当前时间减去 3650 天。那么时间戳在`[Now - 100h, Now + 100y)`内的会保存在一级存储,时间戳在`[Now - 100d, Now - 100h)`内的会保存在二级存储,时间戳在`[Now - 3650d, Now - 100d)`内的会保存在三级存储。社区版不支持多级存储功能,只能配置一个 KEEP 值,如果配置多个,则取其最大者。如果时间戳不在有效时间范围内,TDengine 将返回错误“Timestamp out of range"。 +![Keep timerange 示意图](./pic/database-keep.jpg) + +#### 语法说明 1. 可以指定要插入值的列,对于未指定的列数据库将自动填充为 NULL。 @@ -56,22 +62,24 @@ INSERT INTO ```sql INSERT INTO d1001 USING meters TAGS('Beijing.Chaoyang', 2) VALUES('a'); ``` + 6. 对于向多个子表插入数据的情况,依然会有部分数据写入失败,部分数据写入成功的情况。这是因为多个子表可能分布在不同的 VNODE 上,客户端将 INSERT 语句完整解析后,将数据发往各个涉及的 VNODE 上,每个 VNODE 独立进行写入操作。如果某个 VNODE 因为某些原因(比如网络问题或磁盘故障)导致写入失败,并不会影响其他 VNODE 节点的写入。 7. 主键列值必须指定且不能为 NULL。 -**正常语法说明** +#### 正常语法说明 1. USING 子句是自动建表语法。如果用户在写数据时并不确定某个表是否存在,此时可以在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。自动建表时,要求必须以超级表为模板,并写明数据表的 TAGS 取值。可以只是指定部分 TAGS 列的取值,未被指定的 TAGS 列将置为 NULL。 2. 可以使用 `INSERT ... subquery` 语句将 TDengine 中的数据插入到指定表中。subquery 可以是任意的查询语句。此语法只能用于子表和普通表,且不支持自动建表。 -**超级表语法说明** +#### 超级表语法说明 1. 在 field_name 列表中必须指定 tbname 列,否则报错. tbname列是子表名, 类型是字符串. 其中字符不用转义, 不能包含点‘.‘ 2. 在 field_name 列表中支持标签列,当子表已经存在时,指定标签值并不会触发标签值的修改;当子表不存在时会使用所指定的标签值建立子表. 如果没有指定任何标签列,则把所有标签列的值设置为NULL 3. 不支持参数绑定写入 + ## 插入一条记录 指定已经创建好的数据子表的表名,并通过 VALUES 关键字提供一行或多行数据,即可向数据库写入这些数据。例如,执行如下语句可以写入一行记录: @@ -154,15 +162,18 @@ INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/c INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile_21001.csv' d21002 USING meters (groupId) TAGS (2) FILE '/tmp/csvfile_21002.csv'; ``` + ## 向超级表插入数据并自动创建子表 自动建表, 表名通过 tbname 列指定 + ```sql INSERT INTO meters(tbname, location, groupId, ts, current, voltage, phase) VALUES ('d31001', 'California.SanFrancisco', 2, '2021-07-13 14:06:34.630', 10.2, 219, 0.32) ('d31001', 'California.SanFrancisco', 2, '2021-07-13 14:06:35.779', 10.15, 217, 0.33) ('d31002', NULL, 2, '2021-07-13 14:06:34.255', 10.15, 217, 0.33) ``` + ## 通过 CSV 文件向超级表插入数据并自动创建子表 根据 csv 文件内容,为 超级表创建子表,并填充相应 column 与 tag diff --git a/docs/zh/14-reference/03-taos-sql/pic/database-keep.jpg b/docs/zh/14-reference/03-taos-sql/pic/database-keep.jpg new file mode 100644 index 0000000000000000000000000000000000000000..248a9041d34ec5b3ed9d64ba8b711d1510931aab GIT binary patch literal 116011 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 Pg1Wj%kX5(&H~+r?INgwf literal 0 HcmV?d00001 From d7cee30914100d070ebbf82891071d6ed8b75cd0 Mon Sep 17 00:00:00 2001 From: haoranchen Date: Thu, 14 Nov 2024 19:42:52 +0800 Subject: [PATCH 23/60] Update 3.3.4.3.md --- docs/zh/28-releases/03-notes/3.3.4.3.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/zh/28-releases/03-notes/3.3.4.3.md b/docs/zh/28-releases/03-notes/3.3.4.3.md index 9ded536872..8ffd5802ed 100644 --- a/docs/zh/28-releases/03-notes/3.3.4.3.md +++ b/docs/zh/28-releases/03-notes/3.3.4.3.md @@ -3,6 +3,12 @@ title: 3.3.4.3 版本说明 sidebar_label: 3.3.4.3 description: 3.3.4.3 版本说明 --- + +### 行为变更及兼容性 +1. 多副本流计算中必须使用 snode +1. 增加了流计算的兼容性保证机制,避免后续函数变更产生新的兼容性问题,但之前版本的流计算必须重建,具体参见 https://docs.taosdata.com/advanced/stream/#流计算升级故障恢复 +1. 调整 case when 语句结果类型的判断方法 + ### 新特性 1. 新功能:流计算的 TWA 函数支持时间驱动的结果推送模式 1. 新功能:流计算的 Interp 函数支持时间驱动的结果推送模式 From 1c940b23353d330cc59ca2f92b7964fa442aec77 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Thu, 14 Nov 2024 19:46:21 +0800 Subject: [PATCH 24/60] fix test case --- tests/army/storage/compressBasic.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/army/storage/compressBasic.py b/tests/army/storage/compressBasic.py index f24c4dd288..260461d0e4 100644 --- a/tests/army/storage/compressBasic.py +++ b/tests/army/storage/compressBasic.py @@ -137,7 +137,18 @@ class TDTestCase(TBase): defEncodes = [ "delta-i","delta-i","simple8b","simple8b","simple8b","simple8b","simple8b","simple8b", "simple8b","simple8b","delta-d","delta-d","bit-packing", "disabled","disabled","disabled","disabled"] - + compressDefaultDict = {}; + compressDefaultDict["BOOL"] = "zstd" + compressDefaultDict["TINYINT"] = "zlib" + compressDefaultDict["SMALLINT"] = "zlib" + compressDefaultDict["INT"] = "lz4" + compressDefaultDict["BIGINT"] = "lz4" + compressDefaultDict["FLOAT"] = "lz4" + compressDefaultDict["DOUBLE"] = "lz4" + compressDefaultDict["VARCHAR"] = "lz4" + compressDefaultDict["TIMESTAMP"] = "zstd" + compressDefaultDict["NCHAR"] = "zstd" + count = tdSql.getRows() for i in range(count): node = tdSql.getData(i, 3) @@ -145,7 +156,7 @@ class TDTestCase(TBase): break # check tdSql.checkData(i, 4, defEncodes[i]) - tdSql.checkData(i, 5, self.defCompress) + tdSql.checkData(i, 5, compressDefaultDict[tdSql.getData(i, 2)]) tdSql.checkData(i, 6, self.defLevel) # geometry encode is disabled From 72917aca9c5751f9e2442e03589c391555ff9277 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Thu, 14 Nov 2024 04:52:15 -0800 Subject: [PATCH 25/60] update case --- tests/army/storage/compressBasic.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tests/army/storage/compressBasic.py b/tests/army/storage/compressBasic.py index 260461d0e4..5882c9ffbd 100644 --- a/tests/army/storage/compressBasic.py +++ b/tests/army/storage/compressBasic.py @@ -33,7 +33,7 @@ class TDTestCase(TBase): "compressMsgSize" : "100", } # compress - compresses = ["lz4","tsz","zlib","zstd","disabled","xz"] + compresses = ["lz4","zlib","zstd","disabled","xz"] # level levels = ["high","medium","low"] @@ -145,9 +145,16 @@ class TDTestCase(TBase): compressDefaultDict["BIGINT"] = "lz4" compressDefaultDict["FLOAT"] = "lz4" compressDefaultDict["DOUBLE"] = "lz4" - compressDefaultDict["VARCHAR"] = "lz4" - compressDefaultDict["TIMESTAMP"] = "zstd" + compressDefaultDict["VARCHAR"] = "zstd" + compressDefaultDict["TIMESTAMP"] = "lz4" compressDefaultDict["NCHAR"] = "zstd" + compressDefaultDict["TINYINT UNSIGNED"] = "zlib" + compressDefaultDict["SMALLINT UNSIGNED"] = "zlib" + compressDefaultDict["INT UNSIGNED"] = "lz4" + compressDefaultDict["BIGINT UNSIGNED"] = "lz4" + compressDefaultDict["NCHAR"] = "zstd" + compressDefaultDict["BLOB"] = "lz4" + compressDefaultDict["VARBINARY"] = "zstd" count = tdSql.getRows() for i in range(count): @@ -155,8 +162,13 @@ class TDTestCase(TBase): if node == "TAG": break # check - tdSql.checkData(i, 4, defEncodes[i]) - tdSql.checkData(i, 5, compressDefaultDict[tdSql.getData(i, 2)]) + tdLog.info(f"check default encode {tdSql.getData(i, 1)}") + #tdLog.info(f"check default encode compressDefaultDict[tdSql.getData(i, 2)]") + defaultValue = compressDefaultDict[tdSql.getData(i, 1)] + if defaultValue == None: + defaultValue = self.defCompress + tdLog.info(f"check default compress {tdSql.getData(i, 1)} {defaultValue}") + tdSql.checkData(i, 5, defaultValue) tdSql.checkData(i, 6, self.defLevel) # geometry encode is disabled @@ -198,8 +210,8 @@ class TDTestCase(TBase): for i in range(self.colCnt - 1): col = f"c{i}" sql = f"alter table {tbname} modify column {col} COMPRESS '{comp}';" - tdSql.execute(sql, show=True) - self.checkDataDesc(tbname, i + 1, 5, comp) + #tdSql.execute(sql, show=False) + #self.checkDataDesc(tbname, i + 1, 5, comp) self.writeData(1000) # alter float(c9) double(c10) to tsz @@ -337,6 +349,7 @@ class TDTestCase(TBase): while offset < count: sql = f"select * from {tbname} limit {step} offset {offset}" + tdLog.info(sql) tdSql.query(sql) self.autoGen.dataCorrect(tdSql.res, tdSql.getRows(), step) offset += step From ded0e954ba317285d23b38da070c760287f6bd3c Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Thu, 14 Nov 2024 21:12:19 +0800 Subject: [PATCH 26/60] update case --- utils/test/c/tmq_taosx_ci.c | 56 ++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/utils/test/c/tmq_taosx_ci.c b/utils/test/c/tmq_taosx_ci.c index cd70dd88f5..370b18ae68 100644 --- a/utils/test/c/tmq_taosx_ci.c +++ b/utils/test/c/tmq_taosx_ci.c @@ -65,12 +65,12 @@ static void msg_process(TAOS_RES* msg) { if (g_fp && strcmp(result, "") != 0) { // RES_TYPE__TMQ_BATCH_META if ((*(int8_t*)msg) == 5) { - cJSON* pJson = cJSON_Parse(result); - cJSON* pJsonArray = cJSON_GetObjectItem(pJson, "metas"); + cJSON* pJson = cJSON_Parse(result); + cJSON* pJsonArray = cJSON_GetObjectItem(pJson, "metas"); int32_t num = cJSON_GetArraySize(pJsonArray); for (int32_t i = 0; i < num; i++) { cJSON* pJsonItem = cJSON_GetArrayItem(pJsonArray, i); - char* itemStr = cJSON_PrintUnformatted(pJsonItem); + char* itemStr = cJSON_PrintUnformatted(pJsonItem); taosFprintfFile(g_fp, itemStr); tmq_free_json_meta(itemStr); taosFprintfFile(g_fp, "\n"); @@ -489,10 +489,11 @@ int buildStable(TAOS* pConn, TAOS_RES* pRes) { } taos_free_result(pRes); #else - pRes = taos_query(pConn, - "create stream meters_summary_s trigger at_once IGNORE EXPIRED 0 fill_history 1 into meters_summary as select " - "_wstart, max(current) as current, " - "groupid, location from meters partition by groupid, location interval(10m)"); + pRes = taos_query( + pConn, + "create stream meters_summary_s trigger at_once IGNORE EXPIRED 0 fill_history 1 into meters_summary as select " + "_wstart, max(current) as current, " + "groupid, location from meters partition by groupid, location interval(10m)"); if (taos_errno(pRes) != 0) { printf("failed to create super table meters_summary, reason:%s\n", taos_errstr(pRes)); return -1; @@ -632,8 +633,8 @@ tmq_t* build_consumer() { tmq_conf_set(conf, "enable.auto.commit", "true"); tmq_conf_set(conf, "auto.offset.reset", "earliest"); tmq_conf_set(conf, "msg.consume.excluded", "1"); -// tmq_conf_set(conf, "session.timeout.ms", "1000000"); -// tmq_conf_set(conf, "max.poll.interval.ms", "20000"); + // tmq_conf_set(conf, "session.timeout.ms", "1000000"); + // tmq_conf_set(conf, "max.poll.interval.ms", "20000"); if (g_conf.snapShot) { tmq_conf_set(conf, "experimental.snapshot.enable", "true"); @@ -722,7 +723,7 @@ void initLogFile() { "\"level\":\"medium\"},{" "\"name\":\"groupid\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\"," "\"level\":\"medium\"},{\"name\":" - "\"location\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\"," + "\"location\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\"," "\"level\":\"medium\"}],\"tags\":[{\"name\":\"group_id\"," "\"type\":14}" "]}", @@ -750,7 +751,7 @@ void initLogFile() { "\"level\":\"medium\"}" ",{" "\"name\":\"c3\",\"type\":8,\"length\":64,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" - "\"lz4\",\"level\":\"medium\"},{" + "\"zstd\",\"level\":\"medium\"},{" "\"name\":\"c4\",\"type\":5,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":" "\"medium\"}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":" "\"t3\"," @@ -772,7 +773,7 @@ void initLogFile() { "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"columns\":[{\"name\":\"ts\"," "\"type\":9," "\"isPrimarykey\":false,\"encode\":\"delta-i\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":\"c2\"," - "\"type\":10,\"length\":8,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":" + "\"type\":10,\"length\":8,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":" "\"medium\"},{\"name\":\"cc3\",\"type\":5," "\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":\"medium\"}],\"tags\":[]}", "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"jt\",\"columns\":[{\"name\":\"ts\"," @@ -794,7 +795,7 @@ void initLogFile() { "\"medium\"},{\"name\":\"c2\",\"type\":6,\"isPrimarykey\":" "false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{" "\"name\":\"c3\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" - "\"lz4\",\"level\":\"medium\"}]," + "\"zstd\",\"level\":\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" "1}]}", @@ -806,7 +807,7 @@ void initLogFile() { "\"name\":\"c2\",\"type\":6," "\"isPrimarykey\":false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":" "\"c3\"," - "\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":" + "\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":" "\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" @@ -863,7 +864,7 @@ void initLogFile() { "\"level\":\"medium\"},{\"name\":\"c2\",\"type\":6,\"isPrimarykey\":false,\"encode\":\"delta-d\"," "\"compress\":\"lz4\",\"level\":\"medium\"},{" "\"name\":\"c3\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" - "\"lz4\",\"level\":\"medium\"}]," + "\"zstd\",\"level\":\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" "1}]}", @@ -883,7 +884,8 @@ void initLogFile() { "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\"," "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":6,\"colName\":\"c4\"}", - "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\",\"colType\":5}", + "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\"," + "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":7,\"colName\":\"c3\"," "\"colType\":8,\"colLength\":64}", "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":1,\"colName\":\"t2\"," @@ -896,7 +898,7 @@ void initLogFile() { "9,\"isPrimarykey\":false,\"encode\":\"delta-i\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":" "\"c1\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":" "\"medium\"},{\"name\":\"c2\",\"type\":10,\"length\":4," - "\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":\"medium\"}],\"tags\":[]}", + "\"isPrimarykey\":false,\"encode\":\"disabled\",\"zstd\":\"lz4\",\"level\":\"medium\"}],\"tags\":[]}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":5,\"colName\":\"c3\"," "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":7,\"colName\":\"c2\"," @@ -921,7 +923,7 @@ void initLogFile() { "{\"name\":\"c1\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":" "\"medium\"},{\"name\":\"c2\",\"type\":6,\"isPrimarykey\":" "false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":\"c3\",\"type\":8," - "\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":\"medium\"}]," + "\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":1}]}", "{\"type\":\"drop\",\"tableType\":\"super\",\"tableName\":\"st1\"}", @@ -931,7 +933,7 @@ void initLogFile() { "\"level\":\"medium\"},{\"name\":\"c2\",\"type\":6,\"isPrimarykey\":" "false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{" "\"name\":\"c3\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" - "\"lz4\",\"level\":\"medium\"}]," + "\"zstd\",\"level\":\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" "1}]}", @@ -941,7 +943,7 @@ void initLogFile() { "\"c1\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":" "\"medium\"},{\"name\":\"c2\",\"type\":6," "\"isPrimarykey\":false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":\"c3\"," - "\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":" + "\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":" "\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" @@ -985,7 +987,8 @@ void initLogFile() { "\"lz4\",\"level\":\"medium\"},{" "\"name\":\"groupid\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\"," "\"level\":\"medium\"},{\"name\":" - "\"location\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\"," + "\"location\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" + "\"zstd\"," "\"level\":\"medium\"}],\"tags\":[{\"name\":\"group_id\"," "\"type\":" "14}]}", @@ -1012,7 +1015,7 @@ void initLogFile() { "\"level\":\"medium\"},{\"name\":\"c2\",\"type\":6,\"isPrimarykey\":" "false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{" "\"name\":\"c3\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" - "\"lz4\",\"level\":\"medium\"}]," + "\"zstd\",\"level\":\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" "1}]}", @@ -1032,7 +1035,8 @@ void initLogFile() { "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\"," "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":6,\"colName\":\"c4\"}", - "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\",\"colType\":5}", + "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\"," + "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":7,\"colName\":\"c3\"," "\"colType\":8,\"colLength\":64}", "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":1,\"colName\":\"t2\"," @@ -1044,7 +1048,7 @@ void initLogFile() { "9,\"isPrimarykey\":false,\"encode\":\"delta-i\",\"compress\":\"lz4\",\"level\":\"medium\"}" ",{\"name\":\"c1\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\"," "\"level\":\"medium\"},{\"name\":\"c2\",\"type\":10,\"length\":4," - "\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":\"medium\"}],\"tags\":[]}", + "\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":\"medium\"}],\"tags\":[]}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":5,\"colName\":\"c3\"," "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":7,\"colName\":\"c2\"," @@ -1069,7 +1073,7 @@ void initLogFile() { "\"level\":\"medium\"},{\"name\":\"c2\",\"type\":6,\"isPrimarykey\":" "false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{" "\"name\":\"c3\",\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":" - "\"lz4\",\"level\":\"medium\"}]," + "\"zstd\",\"level\":\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" "1}]}", @@ -1079,7 +1083,7 @@ void initLogFile() { "\"c1\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":" "\"medium\"},{\"name\":\"c2\",\"type\":6," "\"isPrimarykey\":false,\"encode\":\"delta-d\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":\"c3\"," - "\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"lz4\",\"level\":" + "\"type\":8,\"length\":16,\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":" "\"medium\"}]," "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\"," "\"type\":" From f9d67724d92027082afc7d1306cdbce7783cd7c3 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Thu, 14 Nov 2024 22:20:25 +0800 Subject: [PATCH 27/60] fix test case --- utils/test/c/tmq_taosx_ci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/test/c/tmq_taosx_ci.c b/utils/test/c/tmq_taosx_ci.c index 370b18ae68..117f9fa2e1 100644 --- a/utils/test/c/tmq_taosx_ci.c +++ b/utils/test/c/tmq_taosx_ci.c @@ -898,7 +898,7 @@ void initLogFile() { "9,\"isPrimarykey\":false,\"encode\":\"delta-i\",\"compress\":\"lz4\",\"level\":\"medium\"},{\"name\":" "\"c1\",\"type\":4,\"isPrimarykey\":false,\"encode\":\"simple8b\",\"compress\":\"lz4\",\"level\":" "\"medium\"},{\"name\":\"c2\",\"type\":10,\"length\":4," - "\"isPrimarykey\":false,\"encode\":\"disabled\",\"zstd\":\"lz4\",\"level\":\"medium\"}],\"tags\":[]}", + "\"isPrimarykey\":false,\"encode\":\"disabled\",\"compress\":\"zstd\",\"level\":\"medium\"}],\"tags\":[]}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":5,\"colName\":\"c3\"," "\"colType\":5}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":7,\"colName\":\"c2\"," From 1a4e1c9d9e972805317d9099ec72d246348d9e86 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Fri, 15 Nov 2024 08:44:59 +0800 Subject: [PATCH 28/60] update tese case --- tests/army/storage/compressBasic.py | 51 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/tests/army/storage/compressBasic.py b/tests/army/storage/compressBasic.py index 5882c9ffbd..fc9c9d11fb 100644 --- a/tests/army/storage/compressBasic.py +++ b/tests/army/storage/compressBasic.py @@ -35,6 +35,25 @@ class TDTestCase(TBase): # compress compresses = ["lz4","zlib","zstd","disabled","xz"] + compressDefaultDict = {}; + compressDefaultDict["BOOL"] = "zstd" + compressDefaultDict["TINYINT"] = "zlib" + compressDefaultDict["SMALLINT"] = "zlib" + compressDefaultDict["INT"] = "lz4" + compressDefaultDict["BIGINT"] = "lz4" + compressDefaultDict["FLOAT"] = "lz4" + compressDefaultDict["DOUBLE"] = "lz4" + compressDefaultDict["VARCHAR"] = "zstd" + compressDefaultDict["TIMESTAMP"] = "lz4" + compressDefaultDict["NCHAR"] = "zstd" + compressDefaultDict["TINYINT UNSIGNED"] = "zlib" + compressDefaultDict["SMALLINT UNSIGNED"] = "zlib" + compressDefaultDict["INT UNSIGNED"] = "lz4" + compressDefaultDict["BIGINT UNSIGNED"] = "lz4" + compressDefaultDict["NCHAR"] = "zstd" + compressDefaultDict["BLOB"] = "lz4" + compressDefaultDict["VARBINARY"] = "zstd" + # level levels = ["high","medium","low"] @@ -137,24 +156,6 @@ class TDTestCase(TBase): defEncodes = [ "delta-i","delta-i","simple8b","simple8b","simple8b","simple8b","simple8b","simple8b", "simple8b","simple8b","delta-d","delta-d","bit-packing", "disabled","disabled","disabled","disabled"] - compressDefaultDict = {}; - compressDefaultDict["BOOL"] = "zstd" - compressDefaultDict["TINYINT"] = "zlib" - compressDefaultDict["SMALLINT"] = "zlib" - compressDefaultDict["INT"] = "lz4" - compressDefaultDict["BIGINT"] = "lz4" - compressDefaultDict["FLOAT"] = "lz4" - compressDefaultDict["DOUBLE"] = "lz4" - compressDefaultDict["VARCHAR"] = "zstd" - compressDefaultDict["TIMESTAMP"] = "lz4" - compressDefaultDict["NCHAR"] = "zstd" - compressDefaultDict["TINYINT UNSIGNED"] = "zlib" - compressDefaultDict["SMALLINT UNSIGNED"] = "zlib" - compressDefaultDict["INT UNSIGNED"] = "lz4" - compressDefaultDict["BIGINT UNSIGNED"] = "lz4" - compressDefaultDict["NCHAR"] = "zstd" - compressDefaultDict["BLOB"] = "lz4" - compressDefaultDict["VARBINARY"] = "zstd" count = tdSql.getRows() for i in range(count): @@ -164,7 +165,7 @@ class TDTestCase(TBase): # check tdLog.info(f"check default encode {tdSql.getData(i, 1)}") #tdLog.info(f"check default encode compressDefaultDict[tdSql.getData(i, 2)]") - defaultValue = compressDefaultDict[tdSql.getData(i, 1)] + defaultValue = self.compressDefaultDict[tdSql.getData(i, 1)] if defaultValue == None: defaultValue = self.defCompress tdLog.info(f"check default compress {tdSql.getData(i, 1)} {defaultValue}") @@ -209,9 +210,15 @@ class TDTestCase(TBase): for comp in comps: for i in range(self.colCnt - 1): col = f"c{i}" - sql = f"alter table {tbname} modify column {col} COMPRESS '{comp}';" - #tdSql.execute(sql, show=False) - #self.checkDataDesc(tbname, i + 1, 5, comp) + sql2= f"desc {tbname}" + tdSql.execute(sql2, show=True) + + defaultValue = self.compressDefaultDict[tdSql.getData(i, 1)] + if defaultValue == None: + defaultValue = self.defCompress + if defaultValue != comp: + tdSql.execute(sql, show=False) + self.checkDataDesc(tbname, i + 1, 5, comp) self.writeData(1000) # alter float(c9) double(c10) to tsz From 2a83a7d263cced3be43d2376ea31a363d30ea5c6 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Fri, 15 Nov 2024 08:49:36 +0800 Subject: [PATCH 29/60] update tese case --- tests/army/storage/compressBasic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/army/storage/compressBasic.py b/tests/army/storage/compressBasic.py index fc9c9d11fb..565bd312a6 100644 --- a/tests/army/storage/compressBasic.py +++ b/tests/army/storage/compressBasic.py @@ -217,6 +217,7 @@ class TDTestCase(TBase): if defaultValue == None: defaultValue = self.defCompress if defaultValue != comp: + sql = f"alter table {tbname} modify column {col} COMPRESS '{comp}';" tdSql.execute(sql, show=False) self.checkDataDesc(tbname, i + 1, 5, comp) self.writeData(1000) From c1a610fd1969dfbbc79a899b84f318e5d5bf30d0 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Fri, 15 Nov 2024 09:17:13 +0800 Subject: [PATCH 30/60] update test case --- tests/army/storage/compressBasic.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/army/storage/compressBasic.py b/tests/army/storage/compressBasic.py index 565bd312a6..446cb920fb 100644 --- a/tests/army/storage/compressBasic.py +++ b/tests/army/storage/compressBasic.py @@ -209,17 +209,6 @@ class TDTestCase(TBase): comps.append(self.compresses[0]) # add lz4 for comp in comps: for i in range(self.colCnt - 1): - col = f"c{i}" - sql2= f"desc {tbname}" - tdSql.execute(sql2, show=True) - - defaultValue = self.compressDefaultDict[tdSql.getData(i, 1)] - if defaultValue == None: - defaultValue = self.defCompress - if defaultValue != comp: - sql = f"alter table {tbname} modify column {col} COMPRESS '{comp}';" - tdSql.execute(sql, show=False) - self.checkDataDesc(tbname, i + 1, 5, comp) self.writeData(1000) # alter float(c9) double(c10) to tsz From d2ec0c37ac7f5d7b2ba156d13063b1a129673f0e Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Fri, 15 Nov 2024 14:01:16 +0800 Subject: [PATCH 31/60] doc: update compress readme --- docs/en/14-reference/03-taos-sql/31-compress.md | 7 ++++--- docs/zh/14-reference/03-taos-sql/32-compress.md | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/en/14-reference/03-taos-sql/31-compress.md b/docs/en/14-reference/03-taos-sql/31-compress.md index 39abfe69bd..f726c8bbe6 100644 --- a/docs/en/14-reference/03-taos-sql/31-compress.md +++ b/docs/en/14-reference/03-taos-sql/31-compress.md @@ -30,11 +30,12 @@ In this article, it specifically refers to the level within the secondary compre | Data Type | Optional Encoding Algorithm | Default Encoding Algorithm | Optional Compression Algorithm|Default Compression Algorithm| Default Compression Level| | :-----------:|:----------:|:-------:|:-------:|:----------:|:----:| -| tinyint/untinyint/smallint/usmallint/int/uint | simple8b| simple8b | lz4/zlib/zstd/xz| lz4 | medium| +| int/uint | simple8b| simple8b | lz4/zlib/zstd/xz| lz4 | medium| +| tinyint/untinyint/smallint/usmallint | simple8b| simple8b | lz4/zlib/zstd/xz| zlib| medium| | bigint/ubigint/timestamp | simple8b/delta-i | delta-i |lz4/zlib/zstd/xz | lz4| medium| |float/double | delta-d|delta-d |lz4/zlib/zstd/xz/tsz|lz4| medium| -|binary/nchar| disabled| disabled|lz4/zlib/zstd/xz| lz4| medium| -|bool| bit-packing| bit-packing| lz4/zlib/zstd/xz| lz4| medium| +|binary/nchar| disabled| disabled|lz4/zlib/zstd/xz| lz4| zstd| +|bool| bit-packing| bit-packing| lz4/zlib/zstd/xz| lz4| zstd| ## SQL diff --git a/docs/zh/14-reference/03-taos-sql/32-compress.md b/docs/zh/14-reference/03-taos-sql/32-compress.md index 0f2b260832..51650c9123 100644 --- a/docs/zh/14-reference/03-taos-sql/32-compress.md +++ b/docs/zh/14-reference/03-taos-sql/32-compress.md @@ -31,11 +31,12 @@ description: 可配置压缩算法 | 数据类型 | 可选编码算法 | 编码算法默认值 | 可选压缩算法|压缩算法默认值| 压缩等级默认值| | :-----------:|:----------:|:-------:|:-------:|:----------:|:----:| -| tinyint/untinyint/smallint/usmallint/int/uint | simple8b| simple8b | lz4/zlib/zstd/xz| lz4 | medium| -| bigint/ubigint/timestamp | simple8b/delta-i | delta-i |lz4/zlib/zstd/xz | lz4| medium| +| int/uint | simple8b| simple8b | lz4/zlib/zstd/xz| lz4 | medium| +| tinyint/untinyint/smallint/usmallint | simple8b| simple8b | lz4/zlib/zstd/xz| zlib | medium| +| bigint/ubigint/timestamp | simple8b/delta-i | delta-i |lz4/zlib/zstd/xz | lz4| medium| |float/double | delta-d|delta-d |lz4/zlib/zstd/xz/tsz|lz4| medium| -|binary/nchar| disabled| disabled|lz4/zlib/zstd/xz| lz4| medium| -|bool| bit-packing| bit-packing| lz4/zlib/zstd/xz| lz4| medium| +|binary/nchar| disabled| disabled|lz4/zlib/zstd/xz| zstd| medium| +|bool| bit-packing| bit-packing| lz4/zlib/zstd/xz| zstd| medium| ## SQL 语法 From 60067acd9068da1892d8d18c1cc221ad990ae24a Mon Sep 17 00:00:00 2001 From: zyyang Date: Fri, 15 Nov 2024 16:26:50 +0800 Subject: [PATCH 32/60] docs(opc): node_id_pattern and browse_name_pattern#TD-31908 --- docs/zh/06-advanced/05-data-in/05-opcua.md | 2 +- docs/zh/06-advanced/05-data-in/06-opcda.md | 2 +- .../05-data-in/pic/opcda-06-point.png | Bin 47554 -> 52329 bytes .../05-data-in/pic/opcua-06-point.png | Bin 63855 -> 59269 bytes 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh/06-advanced/05-data-in/05-opcua.md b/docs/zh/06-advanced/05-data-in/05-opcua.md index 5795528d01..5123dacd1b 100644 --- a/docs/zh/06-advanced/05-data-in/05-opcua.md +++ b/docs/zh/06-advanced/05-data-in/05-opcua.md @@ -150,7 +150,7 @@ CSV 文件中的每个 Row 配置一个 OPC 数据点位。Row 的规则如下 #### 5.2. 选择数据点位 -可以通过配置 **根节点ID**、**命名空间**、**正则匹配** 等条件,对点位进行筛选。 +可以通过配置 **根节点ID**、**命名空间**、**节点ID**、**节点名称** 等条件,对点位进行筛选。 通过配置 **超级表名**、**表名称**,指定数据要写入的超级表、子表。 diff --git a/docs/zh/06-advanced/05-data-in/06-opcda.md b/docs/zh/06-advanced/05-data-in/06-opcda.md index 7da5b89fe6..32ac1c1f8a 100644 --- a/docs/zh/06-advanced/05-data-in/06-opcda.md +++ b/docs/zh/06-advanced/05-data-in/06-opcda.md @@ -126,7 +126,7 @@ CSV 文件中的每个 Row 配置一个 OPC 数据点位。Row 的规则如下 #### 4.2. 选择数据点位 -可以通过配置 **根节点ID** 和 **正则匹配** 作为过滤条件,对点位进行筛选。 +可以通过配置 **根节点ID**、**节点ID**、**节点名称** 作为过滤条件,对点位进行筛选。 通过配置 **超级表名**、**表名称**,指定数据要写入的超级表、子表。 diff --git a/docs/zh/06-advanced/05-data-in/pic/opcda-06-point.png b/docs/zh/06-advanced/05-data-in/pic/opcda-06-point.png index 9ab69fb386cb94b1b9656d68cef1a710b21ed200..b47463dfbb60bb52db723babcfea146bc09ca06c 100644 GIT binary patch literal 52329 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�_w3}_!QbVU1inVW>>MDn2k9m{zKJNgq0 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