diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index 1954f2a415..48c2210f46 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -236,6 +236,7 @@ bool fmIsInterpPseudoColumnFunc(int32_t funcId); bool fmIsGroupKeyFunc(int32_t funcId); bool fmIsBlockDistFunc(int32_t funcId); bool fmIsConstantResFunc(SFunctionNode* pFunc); +bool fmIsSkipScanCheckFunc(int32_t funcId); void getLastCacheDataType(SDataType* pType); SFunctionNode* createFunction(const char* pName, SNodeList* pParameterList); diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index 885e9e5a30..dbbe1d92dc 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -293,6 +293,7 @@ typedef struct SPartitionLogicNode { SNodeList* pPartitionKeys; SNodeList* pTags; SNode* pSubtable; + SNodeList* pAggFuncs; bool needBlockOutputTsOrder; // if true, partition output block will have ts order maintained int32_t pkTsColId; diff --git a/source/libs/function/inc/functionMgtInt.h b/source/libs/function/inc/functionMgtInt.h index 6d23f65cf3..30bd38e7ba 100644 --- a/source/libs/function/inc/functionMgtInt.h +++ b/source/libs/function/inc/functionMgtInt.h @@ -52,6 +52,7 @@ extern "C" { #define FUNC_MGT_INTERP_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(23) #define FUNC_MGT_GEOMETRY_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(24) #define FUNC_MGT_FORBID_SYSTABLE_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(25) +#define FUNC_MGT_SKIP_SCAN_CHECK_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(26) #define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 0057df7902..c62b5946dc 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -3446,7 +3446,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "_group_key", .type = FUNCTION_TYPE_GROUP_KEY, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_KEEP_ORDER_FUNC | FUNC_MGT_SKIP_SCAN_CHECK_FUNC, .translateFunc = translateGroupKey, .getEnvFunc = getGroupKeyFuncEnv, .initFunc = functionSetup, diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index 9e70710fbd..036e4238d4 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -346,6 +346,10 @@ bool fmIsConstantResFunc(SFunctionNode* pFunc) { return true; } +bool fmIsSkipScanCheckFunc(int32_t funcId) { + return isSpecificClassifyFunc(funcId, FUNC_MGT_SKIP_SCAN_CHECK_FUNC); +} + void getLastCacheDataType(SDataType* pType) { pType->bytes = getFirstLastInfoSize(pType->bytes) + VARSTR_HEADER_SIZE; pType->type = TSDB_DATA_TYPE_BINARY; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 3d48036095..bd73b02c80 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -543,6 +543,7 @@ static int32_t logicPartitionCopy(const SPartitionLogicNode* pSrc, SPartitionLog CLONE_NODE_LIST_FIELD(pPartitionKeys); CLONE_NODE_LIST_FIELD(pTags); CLONE_NODE_FIELD(pSubtable); + CLONE_NODE_LIST_FIELD(pAggFuncs); COPY_SCALAR_FIELD(needBlockOutputTsOrder); COPY_SCALAR_FIELD(pkTsColId); COPY_SCALAR_FIELD(pkTsColTbId); diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index a5b9f6dd91..7ce5b638bd 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -1205,6 +1205,7 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyList(pLogicNode->pPartitionKeys); nodesDestroyList(pLogicNode->pTags); nodesDestroyNode(pLogicNode->pSubtable); + nodesDestroyList(pLogicNode->pAggFuncs); break; } case QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC: { diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index 45b2a73822..a3baa5d43a 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -1256,6 +1256,10 @@ static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pS nodesCloneNode(nodesListGetNode(pCxt->pCurrRoot->pTargets, 0))); } + if (TSDB_CODE_SUCCESS == code) { + code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, NULL, fmIsAggFunc, &pPartition->pAggFuncs); + } + if (TSDB_CODE_SUCCESS == code) { pPartition->pPartitionKeys = nodesCloneList(pSelect->pPartitionByList); if (NULL == pPartition->pPartitionKeys) { diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index c81ca0b3d1..d798353140 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -171,11 +171,16 @@ static bool scanPathOptMayBeOptimized(SLogicNode* pNode) { } static bool scanPathOptShouldGetFuncs(SLogicNode* pNode) { + if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) { + if (pNode->pParent && QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode->pParent)) { + if (WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode->pParent)->winType) return true; + } else { + return !scanPathOptHaveNormalCol(((SPartitionLogicNode*)pNode)->pPartitionKeys); + } + } + if ((QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode) && - WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode)->winType) || - (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode) && pNode->pParent && - QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode->pParent) && - WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode->pParent)->winType)) { + WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode)->winType)) { return true; } if (QUERY_NODE_LOGIC_PLAN_AGG == nodeType(pNode)) { @@ -191,30 +196,17 @@ static SNodeList* scanPathOptGetAllFuncs(SLogicNode* pNode) { return ((SWindowLogicNode*)pNode)->pFuncs; case QUERY_NODE_LOGIC_PLAN_AGG: return ((SAggLogicNode*)pNode)->pAggFuncs; + case QUERY_NODE_LOGIC_PLAN_PARTITION: + return ((SPartitionLogicNode*)pNode)->pAggFuncs; default: break; } return NULL; } -static bool scanPathOptNeedOptimizeDataRequire(const SFunctionNode* pFunc) { - if (!fmIsSpecialDataRequiredFunc(pFunc->funcId)) { - return false; - } - SNode* pPara = NULL; - FOREACH(pPara, pFunc->pParameterList) { - if (QUERY_NODE_COLUMN != nodeType(pPara) && QUERY_NODE_VALUE != nodeType(pPara)) { - return false; - } - } - return true; -} - -static bool scanPathOptNeedDynOptimize(const SFunctionNode* pFunc) { - if (!fmIsDynamicScanOptimizedFunc(pFunc->funcId)) { - return false; - } - SNode* pPara = NULL; +static bool scanPathOptIsSpecifiedFuncType(const SFunctionNode* pFunc, bool (*typeCheckFn)(int32_t)) { + if (!typeCheckFn(pFunc->funcId)) return false; + SNode* pPara; FOREACH(pPara, pFunc->pParameterList) { if (QUERY_NODE_COLUMN != nodeType(pPara) && QUERY_NODE_VALUE != nodeType(pPara)) { return false; @@ -232,10 +224,12 @@ static int32_t scanPathOptGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSd FOREACH(pNode, pAllFuncs) { SFunctionNode* pFunc = (SFunctionNode*)pNode; int32_t code = TSDB_CODE_SUCCESS; - if (scanPathOptNeedOptimizeDataRequire(pFunc)) { + if (scanPathOptIsSpecifiedFuncType(pFunc, fmIsSpecialDataRequiredFunc)) { code = nodesListMakeStrictAppend(&pTmpSdrFuncs, nodesCloneNode(pNode)); - } else if (scanPathOptNeedDynOptimize(pFunc)) { + } else if (scanPathOptIsSpecifiedFuncType(pFunc, fmIsDynamicScanOptimizedFunc)) { code = nodesListMakeStrictAppend(&pTmpDsoFuncs, nodesCloneNode(pNode)); + } else if (scanPathOptIsSpecifiedFuncType(pFunc, fmIsSkipScanCheckFunc)) { + continue; } else { otherFunc = true; break;