optimize count()/last() + partition by tbname/tag

This commit is contained in:
wangjiaming0909 2023-09-19 14:56:02 +08:00
parent 05e9f40834
commit 1e53e6cfeb
9 changed files with 32 additions and 25 deletions

View File

@ -236,6 +236,7 @@ bool fmIsInterpPseudoColumnFunc(int32_t funcId);
bool fmIsGroupKeyFunc(int32_t funcId); bool fmIsGroupKeyFunc(int32_t funcId);
bool fmIsBlockDistFunc(int32_t funcId); bool fmIsBlockDistFunc(int32_t funcId);
bool fmIsConstantResFunc(SFunctionNode* pFunc); bool fmIsConstantResFunc(SFunctionNode* pFunc);
bool fmIsSkipScanCheckFunc(int32_t funcId);
void getLastCacheDataType(SDataType* pType); void getLastCacheDataType(SDataType* pType);
SFunctionNode* createFunction(const char* pName, SNodeList* pParameterList); SFunctionNode* createFunction(const char* pName, SNodeList* pParameterList);

View File

@ -293,6 +293,7 @@ typedef struct SPartitionLogicNode {
SNodeList* pPartitionKeys; SNodeList* pPartitionKeys;
SNodeList* pTags; SNodeList* pTags;
SNode* pSubtable; SNode* pSubtable;
SNodeList* pAggFuncs;
bool needBlockOutputTsOrder; // if true, partition output block will have ts order maintained bool needBlockOutputTsOrder; // if true, partition output block will have ts order maintained
int32_t pkTsColId; int32_t pkTsColId;

View File

@ -52,6 +52,7 @@ extern "C" {
#define FUNC_MGT_INTERP_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(23) #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_GEOMETRY_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(24)
#define FUNC_MGT_FORBID_SYSTABLE_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(25) #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) #define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)

View File

@ -3446,7 +3446,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{ {
.name = "_group_key", .name = "_group_key",
.type = FUNCTION_TYPE_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, .translateFunc = translateGroupKey,
.getEnvFunc = getGroupKeyFuncEnv, .getEnvFunc = getGroupKeyFuncEnv,
.initFunc = functionSetup, .initFunc = functionSetup,

View File

@ -346,6 +346,10 @@ bool fmIsConstantResFunc(SFunctionNode* pFunc) {
return true; return true;
} }
bool fmIsSkipScanCheckFunc(int32_t funcId) {
return isSpecificClassifyFunc(funcId, FUNC_MGT_SKIP_SCAN_CHECK_FUNC);
}
void getLastCacheDataType(SDataType* pType) { void getLastCacheDataType(SDataType* pType) {
pType->bytes = getFirstLastInfoSize(pType->bytes) + VARSTR_HEADER_SIZE; pType->bytes = getFirstLastInfoSize(pType->bytes) + VARSTR_HEADER_SIZE;
pType->type = TSDB_DATA_TYPE_BINARY; pType->type = TSDB_DATA_TYPE_BINARY;

View File

@ -543,6 +543,7 @@ static int32_t logicPartitionCopy(const SPartitionLogicNode* pSrc, SPartitionLog
CLONE_NODE_LIST_FIELD(pPartitionKeys); CLONE_NODE_LIST_FIELD(pPartitionKeys);
CLONE_NODE_LIST_FIELD(pTags); CLONE_NODE_LIST_FIELD(pTags);
CLONE_NODE_FIELD(pSubtable); CLONE_NODE_FIELD(pSubtable);
CLONE_NODE_LIST_FIELD(pAggFuncs);
COPY_SCALAR_FIELD(needBlockOutputTsOrder); COPY_SCALAR_FIELD(needBlockOutputTsOrder);
COPY_SCALAR_FIELD(pkTsColId); COPY_SCALAR_FIELD(pkTsColId);
COPY_SCALAR_FIELD(pkTsColTbId); COPY_SCALAR_FIELD(pkTsColTbId);

View File

@ -1205,6 +1205,7 @@ void nodesDestroyNode(SNode* pNode) {
nodesDestroyList(pLogicNode->pPartitionKeys); nodesDestroyList(pLogicNode->pPartitionKeys);
nodesDestroyList(pLogicNode->pTags); nodesDestroyList(pLogicNode->pTags);
nodesDestroyNode(pLogicNode->pSubtable); nodesDestroyNode(pLogicNode->pSubtable);
nodesDestroyList(pLogicNode->pAggFuncs);
break; break;
} }
case QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC: { case QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC: {

View File

@ -1256,6 +1256,10 @@ static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pS
nodesCloneNode(nodesListGetNode(pCxt->pCurrRoot->pTargets, 0))); 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) { if (TSDB_CODE_SUCCESS == code) {
pPartition->pPartitionKeys = nodesCloneList(pSelect->pPartitionByList); pPartition->pPartitionKeys = nodesCloneList(pSelect->pPartitionByList);
if (NULL == pPartition->pPartitionKeys) { if (NULL == pPartition->pPartitionKeys) {

View File

@ -171,11 +171,16 @@ static bool scanPathOptMayBeOptimized(SLogicNode* pNode) {
} }
static bool scanPathOptShouldGetFuncs(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) && if ((QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode) &&
WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode)->winType) || 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)) {
return true; return true;
} }
if (QUERY_NODE_LOGIC_PLAN_AGG == nodeType(pNode)) { if (QUERY_NODE_LOGIC_PLAN_AGG == nodeType(pNode)) {
@ -191,30 +196,17 @@ static SNodeList* scanPathOptGetAllFuncs(SLogicNode* pNode) {
return ((SWindowLogicNode*)pNode)->pFuncs; return ((SWindowLogicNode*)pNode)->pFuncs;
case QUERY_NODE_LOGIC_PLAN_AGG: case QUERY_NODE_LOGIC_PLAN_AGG:
return ((SAggLogicNode*)pNode)->pAggFuncs; return ((SAggLogicNode*)pNode)->pAggFuncs;
case QUERY_NODE_LOGIC_PLAN_PARTITION:
return ((SPartitionLogicNode*)pNode)->pAggFuncs;
default: default:
break; break;
} }
return NULL; return NULL;
} }
static bool scanPathOptNeedOptimizeDataRequire(const SFunctionNode* pFunc) { static bool scanPathOptIsSpecifiedFuncType(const SFunctionNode* pFunc, bool (*typeCheckFn)(int32_t)) {
if (!fmIsSpecialDataRequiredFunc(pFunc->funcId)) { if (!typeCheckFn(pFunc->funcId)) return false;
return false; SNode* pPara;
}
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;
FOREACH(pPara, pFunc->pParameterList) { FOREACH(pPara, pFunc->pParameterList) {
if (QUERY_NODE_COLUMN != nodeType(pPara) && QUERY_NODE_VALUE != nodeType(pPara)) { if (QUERY_NODE_COLUMN != nodeType(pPara) && QUERY_NODE_VALUE != nodeType(pPara)) {
return false; return false;
@ -232,10 +224,12 @@ static int32_t scanPathOptGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSd
FOREACH(pNode, pAllFuncs) { FOREACH(pNode, pAllFuncs) {
SFunctionNode* pFunc = (SFunctionNode*)pNode; SFunctionNode* pFunc = (SFunctionNode*)pNode;
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
if (scanPathOptNeedOptimizeDataRequire(pFunc)) { if (scanPathOptIsSpecifiedFuncType(pFunc, fmIsSpecialDataRequiredFunc)) {
code = nodesListMakeStrictAppend(&pTmpSdrFuncs, nodesCloneNode(pNode)); code = nodesListMakeStrictAppend(&pTmpSdrFuncs, nodesCloneNode(pNode));
} else if (scanPathOptNeedDynOptimize(pFunc)) { } else if (scanPathOptIsSpecifiedFuncType(pFunc, fmIsDynamicScanOptimizedFunc)) {
code = nodesListMakeStrictAppend(&pTmpDsoFuncs, nodesCloneNode(pNode)); code = nodesListMakeStrictAppend(&pTmpDsoFuncs, nodesCloneNode(pNode));
} else if (scanPathOptIsSpecifiedFuncType(pFunc, fmIsSkipScanCheckFunc)) {
continue;
} else { } else {
otherFunc = true; otherFunc = true;
break; break;