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;
|
double ratio;
|
||||||
SArray* pSmaIndexes;
|
SArray* pSmaIndexes;
|
||||||
int8_t cacheLastMode;
|
int8_t cacheLastMode;
|
||||||
|
int8_t stbRewrite;
|
||||||
SArray* pTsmas;
|
SArray* pTsmas;
|
||||||
SArray* tsmaTargetTbVgInfo; // SArray<SVgroupsInfo*>, used for child table or normal table only
|
SArray* tsmaTargetTbVgInfo; // SArray<SVgroupsInfo*>, used for child table or normal table only
|
||||||
SArray* tsmaTargetTbInfo; // SArray<STsmaTargetTbInfo>, 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 {
|
typedef struct SCollectMetaKeyFromExprCxt {
|
||||||
SCollectMetaKeyCxt* pComCxt;
|
SCollectMetaKeyCxt* pComCxt;
|
||||||
bool hasLastRowOrLast;
|
bool hasLastRowOrLast;
|
||||||
|
bool tbnameCollect;
|
||||||
int32_t errCode;
|
int32_t errCode;
|
||||||
} SCollectMetaKeyFromExprCxt;
|
} SCollectMetaKeyFromExprCxt;
|
||||||
|
|
||||||
|
@ -204,6 +205,45 @@ static EDealRes collectMetaKeyFromTempTable(SCollectMetaKeyFromExprCxt* pCxt, ST
|
||||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
|
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) {
|
static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) {
|
||||||
SCollectMetaKeyFromExprCxt* pCxt = pContext;
|
SCollectMetaKeyFromExprCxt* pCxt = pContext;
|
||||||
switch (nodeType(pNode)) {
|
switch (nodeType(pNode)) {
|
||||||
|
@ -213,6 +253,8 @@ static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) {
|
||||||
return collectMetaKeyFromRealTable(pCxt, (SRealTableNode*)pNode);
|
return collectMetaKeyFromRealTable(pCxt, (SRealTableNode*)pNode);
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
return collectMetaKeyFromTempTable(pCxt, (STempTableNode*)pNode);
|
return collectMetaKeyFromTempTable(pCxt, (STempTableNode*)pNode);
|
||||||
|
case QUERY_NODE_OPERATOR:
|
||||||
|
return collectMetaKeyFromOperator(pCxt, (SOperatorNode*)pNode);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +262,7 @@ static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t collectMetaKeyFromExprs(SCollectMetaKeyCxt* pCxt, SNodeList* pList) {
|
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);
|
nodesWalkExprs(pList, collectMetaKeyFromExprImpl, &cxt);
|
||||||
return cxt.errCode;
|
return cxt.errCode;
|
||||||
}
|
}
|
||||||
|
@ -245,6 +287,9 @@ static int32_t reserveDbCfgForLastRow(SCollectMetaKeyCxt* pCxt, SNode* pTable) {
|
||||||
|
|
||||||
static int32_t collectMetaKeyFromSelect(SCollectMetaKeyCxt* pCxt, SSelectStmt* pStmt) {
|
static int32_t collectMetaKeyFromSelect(SCollectMetaKeyCxt* pCxt, SSelectStmt* pStmt) {
|
||||||
SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .hasLastRowOrLast = false, .errCode = TSDB_CODE_SUCCESS};
|
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);
|
nodesWalkSelectStmt(pStmt, SQL_CLAUSE_FROM, collectMetaKeyFromExprImpl, &cxt);
|
||||||
if (TSDB_CODE_SUCCESS == cxt.errCode && cxt.hasLastRowOrLast) {
|
if (TSDB_CODE_SUCCESS == cxt.errCode && cxt.hasLastRowOrLast) {
|
||||||
cxt.errCode = reserveDbCfgForLastRow(pCxt, pStmt->pFromTable);
|
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)) {
|
if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
|
||||||
const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta;
|
const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta;
|
||||||
int32_t nums = pMeta->tableInfo.numOfColumns +
|
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) {
|
for (int32_t i = 0; i < nums; ++i) {
|
||||||
if (invisibleColumn(pCxt->pParseCxt->enableSysInfo, pMeta->tableType, pMeta->schema[i].flags)) {
|
if (invisibleColumn(pCxt->pParseCxt->enableSysInfo, pMeta->tableType, pMeta->schema[i].flags)) {
|
||||||
pCxt->pParseCxt->hasInvisibleCol = true;
|
pCxt->pParseCxt->hasInvisibleCol = true;
|
||||||
|
@ -5964,6 +5964,7 @@ static int32_t isOperatorEqTbnameCond(STranslateContext* pCxt, SOperatorNode* pO
|
||||||
*pRet = false;
|
*pRet = false;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SFunctionNode* pTbnameFunc = NULL;
|
SFunctionNode* pTbnameFunc = NULL;
|
||||||
SValueNode* pValueNode = NULL;
|
SValueNode* pValueNode = NULL;
|
||||||
if (nodeType(pOperator->pLeft) == QUERY_NODE_FUNCTION &&
|
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) {
|
static int32_t findEqCondTbNameInOperatorNode(STranslateContext* pCxt, SNode* pWhere, SEqCondTbNameTableInfo* pInfo, bool* pRet) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
char* pTableAlias = NULL;
|
char* pTableAlias = NULL;
|
||||||
char* pTbNameVal = NULL;
|
|
||||||
bool eqTbnameCond = false, tbnameInCond = false;
|
bool eqTbnameCond = false, tbnameInCond = false;
|
||||||
code = isOperatorEqTbnameCond(pCxt, (SOperatorNode*)pWhere, &pTableAlias, &pInfo->aTbnames, &eqTbnameCond);
|
code = isOperatorEqTbnameCond(pCxt, (SOperatorNode*)pWhere, &pTableAlias, &pInfo->aTbnames, &eqTbnameCond);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
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) {
|
static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt* pSelect, SArray* aTables) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
for (int i = 0; i < taosArrayGetSize(aTables); ++i) {
|
int32_t aTableNum = taosArrayGetSize(aTables);
|
||||||
SEqCondTbNameTableInfo* pInfo = taosArrayGet(aTables, i);
|
int32_t nTbls = 0;
|
||||||
int32_t nTbls = taosArrayGetSize(pInfo->aTbnames);
|
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;
|
int32_t numOfVgs = pInfo->pRealTable->pVgroupList->numOfVgroups;
|
||||||
|
nTbls = taosArrayGetSize(pInfo->aTbnames);
|
||||||
|
|
||||||
SVgroupsInfo* vgsInfo = taosMemoryMalloc(sizeof(SVgroupsInfo) + nTbls * sizeof(SVgroupInfo));
|
SVgroupsInfo* vgsInfo = taosMemoryMalloc(sizeof(SVgroupsInfo) + nTbls * sizeof(SVgroupInfo));
|
||||||
findVgroupsFromEqualTbname(pCxt, pInfo->aTbnames, pInfo->pRealTable->table.dbName, numOfVgs, vgsInfo);
|
findVgroupsFromEqualTbname(pCxt, pInfo->aTbnames, pInfo->pRealTable->table.dbName, numOfVgs, vgsInfo);
|
||||||
|
@ -6237,6 +6298,7 @@ static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt*
|
||||||
} else {
|
} else {
|
||||||
taosMemoryFree(vgsInfo);
|
taosMemoryFree(vgsInfo);
|
||||||
}
|
}
|
||||||
|
stableQuery = pInfo->pRealTable->pMeta->tableType == TSDB_SUPER_TABLE;
|
||||||
vgsInfo = NULL;
|
vgsInfo = NULL;
|
||||||
|
|
||||||
if (pInfo->pRealTable->pTsmas) {
|
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) {
|
static int32_t setTableVgroupsFromEqualTbnameCond(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
|
|
|
@ -169,7 +169,7 @@ class TDTestCase:
|
||||||
tdSql.checkData(3, 2, 4)
|
tdSql.checkData(3, 2, 4)
|
||||||
|
|
||||||
tdSql.query("explain select * from st where tbname='ct1'")
|
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'");
|
tdSql.query("select table_name, vgroup_id from information_schema.ins_tables where db_name='dbvg' and type='CHILD_TABLE'");
|
||||||
print(tdSql.queryResult);
|
print(tdSql.queryResult);
|
||||||
|
|
Loading…
Reference in New Issue