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 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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue