optimize count()/last() + partition by tbname/tag
This commit is contained in:
parent
05e9f40834
commit
1e53e6cfeb
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue