Merge pull request #27549 from taosdata/enh/TS-5312
enh: optimize stable tbname equal query
This commit is contained in:
commit
b542d83fbc
|
@ -214,6 +214,7 @@ typedef struct SRealTableNode {
|
|||
double ratio;
|
||||
SArray* pSmaIndexes;
|
||||
int8_t cacheLastMode;
|
||||
int8_t stbRewrite;
|
||||
SArray* pTsmas;
|
||||
SArray* tsmaTargetTbVgInfo; // SArray<SVgroupsInfo*>, used for child table or normal table only
|
||||
SArray* tsmaTargetTbInfo; // SArray<STsmaTargetTbInfo>, used for child table or normal table only
|
||||
|
|
|
@ -107,6 +107,7 @@ typedef struct SCollectMetaKeyCxt {
|
|||
typedef struct SCollectMetaKeyFromExprCxt {
|
||||
SCollectMetaKeyCxt* pComCxt;
|
||||
bool hasLastRowOrLast;
|
||||
bool tbnameCollect;
|
||||
int32_t errCode;
|
||||
} SCollectMetaKeyFromExprCxt;
|
||||
|
||||
|
@ -204,6 +205,45 @@ static EDealRes collectMetaKeyFromTempTable(SCollectMetaKeyFromExprCxt* pCxt, ST
|
|||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
static int32_t isTbnameEqCondOperator(SOperatorNode* pOperator, char** ppTableName) {
|
||||
if (pOperator->opType != OP_TYPE_EQUAL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SValueNode* pValueNode = NULL;
|
||||
if (nodeType(pOperator->pLeft) == QUERY_NODE_FUNCTION &&
|
||||
0 == strcasecmp(((SFunctionNode*)(pOperator->pLeft))->functionName, "tbname") &&
|
||||
nodeType(pOperator->pRight) == QUERY_NODE_VALUE) {
|
||||
pValueNode = (SValueNode*)pOperator->pRight;
|
||||
} else if (nodeType(pOperator->pRight) == QUERY_NODE_FUNCTION &&
|
||||
0 == strcasecmp(((SFunctionNode*)(pOperator->pRight))->functionName, "tbname") &&
|
||||
nodeType(pOperator->pLeft) == QUERY_NODE_VALUE) {
|
||||
pValueNode = (SValueNode*)pOperator->pLeft;
|
||||
} else {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
*ppTableName = pValueNode->literal;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static EDealRes collectMetaKeyFromOperator(SCollectMetaKeyFromExprCxt* pCxt, SOperatorNode* pOpNode) {
|
||||
if (!pCxt->tbnameCollect) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
char* pTableName = NULL;
|
||||
int32_t code = isTbnameEqCondOperator((SOperatorNode*)pOpNode, &pTableName);
|
||||
if (TSDB_CODE_SUCCESS != code) return DEAL_RES_CONTINUE;
|
||||
if (pTableName) {
|
||||
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pComCxt->pStmt;
|
||||
pCxt->errCode = collectMetaKeyFromRealTableImpl(pCxt->pComCxt, ((SRealTableNode*)pSelect->pFromTable)->table.dbName, pTableName, AUTH_TYPE_READ);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) {
|
||||
SCollectMetaKeyFromExprCxt* pCxt = pContext;
|
||||
switch (nodeType(pNode)) {
|
||||
|
@ -213,6 +253,8 @@ static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) {
|
|||
return collectMetaKeyFromRealTable(pCxt, (SRealTableNode*)pNode);
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
return collectMetaKeyFromTempTable(pCxt, (STempTableNode*)pNode);
|
||||
case QUERY_NODE_OPERATOR:
|
||||
return collectMetaKeyFromOperator(pCxt, (SOperatorNode*)pNode);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -220,7 +262,7 @@ static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) {
|
|||
}
|
||||
|
||||
static int32_t collectMetaKeyFromExprs(SCollectMetaKeyCxt* pCxt, SNodeList* pList) {
|
||||
SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .errCode = TSDB_CODE_SUCCESS};
|
||||
SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .errCode = TSDB_CODE_SUCCESS, .tbnameCollect = false};
|
||||
nodesWalkExprs(pList, collectMetaKeyFromExprImpl, &cxt);
|
||||
return cxt.errCode;
|
||||
}
|
||||
|
@ -245,6 +287,9 @@ static int32_t reserveDbCfgForLastRow(SCollectMetaKeyCxt* pCxt, SNode* pTable) {
|
|||
|
||||
static int32_t collectMetaKeyFromSelect(SCollectMetaKeyCxt* pCxt, SSelectStmt* pStmt) {
|
||||
SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .hasLastRowOrLast = false, .errCode = TSDB_CODE_SUCCESS};
|
||||
if (pStmt->pFromTable && QUERY_NODE_REAL_TABLE == nodeType(pStmt->pFromTable)) {
|
||||
cxt.tbnameCollect = true;
|
||||
}
|
||||
nodesWalkSelectStmt(pStmt, SQL_CLAUSE_FROM, collectMetaKeyFromExprImpl, &cxt);
|
||||
if (TSDB_CODE_SUCCESS == cxt.errCode && cxt.hasLastRowOrLast) {
|
||||
cxt.errCode = reserveDbCfgForLastRow(pCxt, pStmt->pFromTable);
|
||||
|
|
|
@ -1275,7 +1275,7 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p
|
|||
if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
|
||||
const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta;
|
||||
int32_t nums = pMeta->tableInfo.numOfColumns +
|
||||
(igTags ? 0 : ((TSDB_SUPER_TABLE == pMeta->tableType) ? pMeta->tableInfo.numOfTags : 0));
|
||||
(igTags ? 0 : ((TSDB_SUPER_TABLE == pMeta->tableType || ((SRealTableNode*)pTable)->stbRewrite) ? pMeta->tableInfo.numOfTags : 0));
|
||||
for (int32_t i = 0; i < nums; ++i) {
|
||||
if (invisibleColumn(pCxt->pParseCxt->enableSysInfo, pMeta->tableType, pMeta->schema[i].flags)) {
|
||||
pCxt->pParseCxt->hasInvisibleCol = true;
|
||||
|
@ -5964,6 +5964,7 @@ static int32_t isOperatorEqTbnameCond(STranslateContext* pCxt, SOperatorNode* pO
|
|||
*pRet = false;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SFunctionNode* pTbnameFunc = NULL;
|
||||
SValueNode* pValueNode = NULL;
|
||||
if (nodeType(pOperator->pLeft) == QUERY_NODE_FUNCTION &&
|
||||
|
@ -6041,7 +6042,6 @@ static int32_t isOperatorTbnameInCond(STranslateContext* pCxt, SOperatorNode* pO
|
|||
static int32_t findEqCondTbNameInOperatorNode(STranslateContext* pCxt, SNode* pWhere, SEqCondTbNameTableInfo* pInfo, bool* pRet) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
char* pTableAlias = NULL;
|
||||
char* pTbNameVal = NULL;
|
||||
bool eqTbnameCond = false, tbnameInCond = false;
|
||||
code = isOperatorEqTbnameCond(pCxt, (SOperatorNode*)pWhere, &pTableAlias, &pInfo->aTbnames, &eqTbnameCond);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -6222,12 +6222,73 @@ static void findVgroupsFromEqualTbname(STranslateContext* pCxt, SArray* aTbnames
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t replaceToChildTableQuery(STranslateContext* pCxt, SEqCondTbNameTableInfo* pInfo) {
|
||||
SName snameTb;
|
||||
int32_t code = 0;
|
||||
SRealTableNode* pRealTable = pInfo->pRealTable;
|
||||
char* tbName = taosArrayGetP(pInfo->aTbnames, 0);
|
||||
(void)toName(pCxt->pParseCxt->acctId, pRealTable->table.dbName, tbName, &snameTb);
|
||||
|
||||
STableMeta* pMeta = NULL;
|
||||
TAOS_CHECK_RETURN(catalogGetCachedTableMeta(pCxt->pParseCxt->pCatalog, &snameTb, &pMeta));
|
||||
if (NULL == pMeta || TSDB_CHILD_TABLE != pMeta->tableType || pMeta->suid != pRealTable->pMeta->suid) {
|
||||
goto _return;
|
||||
}
|
||||
|
||||
pRealTable->pMeta->uid = pMeta->uid;
|
||||
pRealTable->pMeta->vgId = pMeta->vgId;
|
||||
pRealTable->pMeta->tableType = pMeta->tableType;
|
||||
tstrncpy(pRealTable->table.tableName, tbName, sizeof(pRealTable->table.tableName));
|
||||
|
||||
pRealTable->stbRewrite = true;
|
||||
|
||||
if (pRealTable->pTsmas) {
|
||||
// if select from a child table, fetch it's corresponding tsma target child table infos
|
||||
char buf[TSDB_TABLE_FNAME_LEN + TSDB_TABLE_NAME_LEN + 1];
|
||||
for (int32_t i = 0; i < pRealTable->pTsmas->size; ++i) {
|
||||
STableTSMAInfo* pTsma = taosArrayGetP(pRealTable->pTsmas, i);
|
||||
SName tsmaTargetTbName = {0};
|
||||
(void)toName(pCxt->pParseCxt->acctId, pRealTable->table.dbName, "", &tsmaTargetTbName);
|
||||
int32_t len = snprintf(buf, TSDB_TABLE_FNAME_LEN + TSDB_TABLE_NAME_LEN, "%s.%s_%s", pTsma->dbFName, pTsma->name,
|
||||
pRealTable->table.tableName);
|
||||
len = taosCreateMD5Hash(buf, len);
|
||||
strncpy(tsmaTargetTbName.tname, buf, MD5_OUTPUT_LEN);
|
||||
STsmaTargetTbInfo ctbInfo = {0};
|
||||
if (!pRealTable->tsmaTargetTbInfo) {
|
||||
pRealTable->tsmaTargetTbInfo = taosArrayInit(pRealTable->pTsmas->size, sizeof(STsmaTargetTbInfo));
|
||||
if (!pRealTable->tsmaTargetTbInfo) {
|
||||
code = terrno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sprintf(ctbInfo.tableName, "%s", tsmaTargetTbName.tname);
|
||||
ctbInfo.uid = pMeta->uid;
|
||||
|
||||
if (NULL == taosArrayPush(pRealTable->tsmaTargetTbInfo, &ctbInfo)) {
|
||||
code = terrno;
|
||||
goto _return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_return:
|
||||
|
||||
taosMemoryFree(pMeta);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt* pSelect, SArray* aTables) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
for (int i = 0; i < taosArrayGetSize(aTables); ++i) {
|
||||
SEqCondTbNameTableInfo* pInfo = taosArrayGet(aTables, i);
|
||||
int32_t nTbls = taosArrayGetSize(pInfo->aTbnames);
|
||||
int32_t aTableNum = taosArrayGetSize(aTables);
|
||||
int32_t nTbls = 0;
|
||||
bool stableQuery = false;
|
||||
SEqCondTbNameTableInfo* pInfo = NULL;
|
||||
|
||||
qDebug("start to update stable vg for tbname optimize, aTableNum:%d", aTableNum);
|
||||
for (int i = 0; i < aTableNum; ++i) {
|
||||
pInfo = taosArrayGet(aTables, i);
|
||||
int32_t numOfVgs = pInfo->pRealTable->pVgroupList->numOfVgroups;
|
||||
nTbls = taosArrayGetSize(pInfo->aTbnames);
|
||||
|
||||
SVgroupsInfo* vgsInfo = taosMemoryMalloc(sizeof(SVgroupsInfo) + nTbls * sizeof(SVgroupInfo));
|
||||
findVgroupsFromEqualTbname(pCxt, pInfo->aTbnames, pInfo->pRealTable->table.dbName, numOfVgs, vgsInfo);
|
||||
|
@ -6237,6 +6298,7 @@ static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt*
|
|||
} else {
|
||||
taosMemoryFree(vgsInfo);
|
||||
}
|
||||
stableQuery = pInfo->pRealTable->pMeta->tableType == TSDB_SUPER_TABLE;
|
||||
vgsInfo = NULL;
|
||||
|
||||
if (pInfo->pRealTable->pTsmas) {
|
||||
|
@ -6276,7 +6338,14 @@ static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt*
|
|||
}
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
qDebug("before ctbname optimize, code:%d, aTableNum:%d, nTbls:%d, stableQuery:%d", code, aTableNum, nTbls, stableQuery);
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code && 1 == aTableNum && 1 == nTbls && stableQuery && NULL == pInfo->pRealTable->pTsmas) {
|
||||
code = replaceToChildTableQuery(pCxt, pInfo);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t setTableVgroupsFromEqualTbnameCond(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
|
|
|
@ -169,7 +169,7 @@ class TDTestCase:
|
|||
tdSql.checkData(3, 2, 4)
|
||||
|
||||
tdSql.query("explain select * from st where tbname='ct1'")
|
||||
tdSql.checkRows(2)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
tdSql.query("select table_name, vgroup_id from information_schema.ins_tables where db_name='dbvg' and type='CHILD_TABLE'");
|
||||
print(tdSql.queryResult);
|
||||
|
|
Loading…
Reference in New Issue