enh: when there is _wend and _wduration in the query, you can use tsma optimization
This commit is contained in:
parent
b686e1fd4d
commit
0fd305158d
|
@ -4569,8 +4569,89 @@ typedef struct SSampleAstInfo {
|
||||||
SNode* pSliding;
|
SNode* pSliding;
|
||||||
SNodeList* pPartitionByList;
|
SNodeList* pPartitionByList;
|
||||||
STableMeta* pRollupTableMeta;
|
STableMeta* pRollupTableMeta;
|
||||||
|
bool createSmaIndex;
|
||||||
} SSampleAstInfo;
|
} SSampleAstInfo;
|
||||||
|
|
||||||
|
static int32_t buildTableForSampleAst(SSampleAstInfo* pInfo, SNode** pOutput) {
|
||||||
|
SRealTableNode* pTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE);
|
||||||
|
if (NULL == pTable) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
snprintf(pTable->table.dbName, sizeof(pTable->table.dbName), "%s", pInfo->pDbName);
|
||||||
|
snprintf(pTable->table.tableName, sizeof(pTable->table.tableName), "%s", pInfo->pTableName);
|
||||||
|
TSWAP(pTable->pMeta, pInfo->pRollupTableMeta);
|
||||||
|
*pOutput = (SNode*)pTable;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t addWstartToSampleProjects(SNodeList* pProjectionList) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
strcpy(pFunc->functionName, "_wstart");
|
||||||
|
return nodesListPushFront(pProjectionList, (SNode*)pFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t addWendToSampleProjects(SNodeList* pProjectionList) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
strcpy(pFunc->functionName, "_wend");
|
||||||
|
return nodesListAppend(pProjectionList, (SNode*)pFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t addWdurationToSampleProjects(SNodeList* pProjectionList) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
strcpy(pFunc->functionName, "_wduration");
|
||||||
|
return nodesListAppend(pProjectionList, (SNode*)pFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t buildProjectsForSampleAst(SSampleAstInfo* pInfo, SNodeList** pList) {
|
||||||
|
SNodeList* pProjectionList = pInfo->pFuncs;
|
||||||
|
pInfo->pFuncs = NULL;
|
||||||
|
|
||||||
|
int32_t code = addWstartToSampleProjects(pProjectionList);
|
||||||
|
if (TSDB_CODE_SUCCESS == code && pInfo->createSmaIndex) {
|
||||||
|
code = addWendToSampleProjects(pProjectionList);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addWdurationToSampleProjects(pProjectionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
SNode* pProject = NULL;
|
||||||
|
FOREACH(pProject, pProjectionList) { sprintf(((SExprNode*)pProject)->aliasName, "#%p", pProject); }
|
||||||
|
*pList = pProjectionList;
|
||||||
|
} else {
|
||||||
|
nodesDestroyList(pProjectionList);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t buildIntervalForSampleAst(SSampleAstInfo* pInfo, SNode** pOutput) {
|
||||||
|
SIntervalWindowNode* pInterval = (SIntervalWindowNode*)nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW);
|
||||||
|
if (NULL == pInterval) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
TSWAP(pInterval->pInterval, pInfo->pInterval);
|
||||||
|
TSWAP(pInterval->pOffset, pInfo->pOffset);
|
||||||
|
TSWAP(pInterval->pSliding, pInfo->pSliding);
|
||||||
|
pInterval->pCol = nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
|
if (NULL == pInterval->pCol) {
|
||||||
|
nodesDestroyNode((SNode*)pInterval);
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
((SColumnNode*)pInterval->pCol)->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
||||||
|
strcpy(((SColumnNode*)pInterval->pCol)->colName, ROWTS_PSEUDO_COLUMN_NAME);
|
||||||
|
*pOutput = (SNode*)pInterval;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, char** pAst, int32_t* pLen, char** pExpr,
|
static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, char** pAst, int32_t* pLen, char** pExpr,
|
||||||
int32_t* pExprLen) {
|
int32_t* pExprLen) {
|
||||||
SSelectStmt* pSelect = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT);
|
SSelectStmt* pSelect = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT);
|
||||||
|
@ -4579,48 +4660,18 @@ static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, ch
|
||||||
}
|
}
|
||||||
sprintf(pSelect->stmtName, "%p", pSelect);
|
sprintf(pSelect->stmtName, "%p", pSelect);
|
||||||
|
|
||||||
SRealTableNode* pTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE);
|
int32_t code = buildTableForSampleAst(pInfo, &pSelect->pFromTable);
|
||||||
if (NULL == pTable) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
nodesDestroyNode((SNode*)pSelect);
|
code = buildProjectsForSampleAst(pInfo, &pSelect->pProjectionList);
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
snprintf(pTable->table.dbName, sizeof(pTable->table.dbName), "%s", pInfo->pDbName);
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
snprintf(pTable->table.tableName, sizeof(pTable->table.tableName), "%s", pInfo->pTableName);
|
TSWAP(pSelect->pPartitionByList, pInfo->pPartitionByList);
|
||||||
TSWAP(pTable->pMeta, pInfo->pRollupTableMeta);
|
code = buildIntervalForSampleAst(pInfo, &pSelect->pWindow);
|
||||||
pSelect->pFromTable = (SNode*)pTable;
|
|
||||||
|
|
||||||
TSWAP(pSelect->pProjectionList, pInfo->pFuncs);
|
|
||||||
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
|
||||||
if (NULL == pSelect->pProjectionList || NULL == pFunc) {
|
|
||||||
nodesDestroyNode((SNode*)pSelect);
|
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
strcpy(pFunc->functionName, "_wstart");
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
nodesListPushFront(pSelect->pProjectionList, (SNode*)pFunc);
|
pCxt->createStream = true;
|
||||||
SNode* pProject = NULL;
|
code = translateQuery(pCxt, (SNode*)pSelect);
|
||||||
FOREACH(pProject, pSelect->pProjectionList) { sprintf(((SExprNode*)pProject)->aliasName, "#%p", pProject); }
|
|
||||||
|
|
||||||
TSWAP(pSelect->pPartitionByList, pInfo->pPartitionByList);
|
|
||||||
|
|
||||||
SIntervalWindowNode* pInterval = (SIntervalWindowNode*)nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW);
|
|
||||||
if (NULL == pInterval) {
|
|
||||||
nodesDestroyNode((SNode*)pSelect);
|
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
pSelect->pWindow = (SNode*)pInterval;
|
|
||||||
TSWAP(pInterval->pInterval, pInfo->pInterval);
|
|
||||||
TSWAP(pInterval->pOffset, pInfo->pOffset);
|
|
||||||
TSWAP(pInterval->pSliding, pInfo->pSliding);
|
|
||||||
pInterval->pCol = nodesMakeNode(QUERY_NODE_COLUMN);
|
|
||||||
if (NULL == pInterval->pCol) {
|
|
||||||
nodesDestroyNode((SNode*)pSelect);
|
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
((SColumnNode*)pInterval->pCol)->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
|
||||||
strcpy(((SColumnNode*)pInterval->pCol)->colName, ROWTS_PSEUDO_COLUMN_NAME);
|
|
||||||
|
|
||||||
pCxt->createStream = true;
|
|
||||||
int32_t code = translateQuery(pCxt, (SNode*)pSelect);
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = nodesNodeToString((SNode*)pSelect, false, pAst, pLen);
|
code = nodesNodeToString((SNode*)pSelect, false, pAst, pLen);
|
||||||
}
|
}
|
||||||
|
@ -5162,6 +5213,7 @@ static int32_t getSmaIndexSql(STranslateContext* pCxt, char** pSql, int32_t* pLe
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t buildSampleAstInfoByIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt, SSampleAstInfo* pInfo) {
|
static int32_t buildSampleAstInfoByIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt, SSampleAstInfo* pInfo) {
|
||||||
|
pInfo->createSmaIndex = true;
|
||||||
pInfo->pDbName = pStmt->dbName;
|
pInfo->pDbName = pStmt->dbName;
|
||||||
pInfo->pTableName = pStmt->tableName;
|
pInfo->pTableName = pStmt->tableName;
|
||||||
pInfo->pFuncs = nodesCloneList(pStmt->pOptions->pFuncs);
|
pInfo->pFuncs = nodesCloneList(pStmt->pOptions->pFuncs);
|
||||||
|
|
|
@ -1284,18 +1284,14 @@ static int32_t smaIndexOptFindSmaFunc(SNode* pQueryFunc, SNodeList* pSmaFuncs) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeList* pSmaFuncs, SNodeList** pOutput,
|
static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeList* pSmaFuncs,
|
||||||
int32_t* pWStrartIndex) {
|
SNodeList** pOutput) {
|
||||||
SNodeList* pCols = NULL;
|
SNodeList* pCols = NULL;
|
||||||
SNode* pFunc = NULL;
|
SNode* pFunc = NULL;
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
int32_t index = 0;
|
int32_t index = 0;
|
||||||
int32_t smaFuncIndex = -1;
|
int32_t smaFuncIndex = -1;
|
||||||
*pWStrartIndex = -1;
|
|
||||||
FOREACH(pFunc, pFuncs) {
|
FOREACH(pFunc, pFuncs) {
|
||||||
if (FUNCTION_TYPE_WSTART == ((SFunctionNode*)pFunc)->funcType) {
|
|
||||||
*pWStrartIndex = index;
|
|
||||||
}
|
|
||||||
smaFuncIndex = smaIndexOptFindSmaFunc(pFunc, pSmaFuncs);
|
smaFuncIndex = smaIndexOptFindSmaFunc(pFunc, pSmaFuncs);
|
||||||
if (smaFuncIndex < 0) {
|
if (smaFuncIndex < 0) {
|
||||||
break;
|
break;
|
||||||
|
@ -1317,8 +1313,7 @@ static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNo
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList** pCols,
|
static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList** pCols) {
|
||||||
int32_t* pWStrartIndex) {
|
|
||||||
SWindowLogicNode* pWindow = (SWindowLogicNode*)pScan->node.pParent;
|
SWindowLogicNode* pWindow = (SWindowLogicNode*)pScan->node.pParent;
|
||||||
if (!smaIndexOptEqualInterval(pScan, pWindow, pIndex)) {
|
if (!smaIndexOptEqualInterval(pScan, pWindow, pIndex)) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -1326,14 +1321,14 @@ static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo
|
||||||
SNodeList* pSmaFuncs = NULL;
|
SNodeList* pSmaFuncs = NULL;
|
||||||
int32_t code = nodesStringToList(pIndex->expr, &pSmaFuncs);
|
int32_t code = nodesStringToList(pIndex->expr, &pSmaFuncs);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = smaIndexOptCreateSmaCols(pWindow->pFuncs, pIndex->dstTbUid, pSmaFuncs, pCols, pWStrartIndex);
|
code = smaIndexOptCreateSmaCols(pWindow->pFuncs, pIndex->dstTbUid, pSmaFuncs, pCols);
|
||||||
}
|
}
|
||||||
nodesDestroyList(pSmaFuncs);
|
nodesDestroyList(pSmaFuncs);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t smaIndexOptApplyIndex(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex,
|
static int32_t smaIndexOptApplyIndex(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex,
|
||||||
SNodeList* pSmaCols, int32_t wstrartIndex) {
|
SNodeList* pSmaCols) {
|
||||||
SLogicNode* pSmaScan = NULL;
|
SLogicNode* pSmaScan = NULL;
|
||||||
int32_t code = smaIndexOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan);
|
int32_t code = smaIndexOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
@ -1350,10 +1345,9 @@ static int32_t smaIndexOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogi
|
||||||
for (int32_t i = 0; i < nindexes; ++i) {
|
for (int32_t i = 0; i < nindexes; ++i) {
|
||||||
STableIndexInfo* pIndex = taosArrayGet(pScan->pSmaIndexes, i);
|
STableIndexInfo* pIndex = taosArrayGet(pScan->pSmaIndexes, i);
|
||||||
SNodeList* pSmaCols = NULL;
|
SNodeList* pSmaCols = NULL;
|
||||||
int32_t wstrartIndex = -1;
|
code = smaIndexOptCouldApplyIndex(pScan, pIndex, &pSmaCols);
|
||||||
code = smaIndexOptCouldApplyIndex(pScan, pIndex, &pSmaCols, &wstrartIndex);
|
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pSmaCols) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pSmaCols) {
|
||||||
code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols, wstrartIndex);
|
code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols);
|
||||||
taosArrayDestroyEx(pScan->pSmaIndexes, smaIndexOptDestroySmaIndex);
|
taosArrayDestroyEx(pScan->pSmaIndexes, smaIndexOptDestroySmaIndex);
|
||||||
pScan->pSmaIndexes = NULL;
|
pScan->pSmaIndexes = NULL;
|
||||||
pCxt->optimized = true;
|
pCxt->optimized = true;
|
||||||
|
|
Loading…
Reference in New Issue