remainGroups

This commit is contained in:
Bob Liu 2024-01-02 15:45:03 +08:00
parent 673d3bc376
commit 85ba9a4a5f
4 changed files with 72 additions and 90 deletions

View File

@ -105,6 +105,7 @@ typedef struct STableListInfo {
int32_t* groupOffset; // keep the offset value for each group in the tableList int32_t* groupOffset; // keep the offset value for each group in the tableList
SArray* pTableList; SArray* pTableList;
SHashObj* map; // speedup acquire the tableQueryInfo by table uid SHashObj* map; // speedup acquire the tableQueryInfo by table uid
SHashObj* remainGroups; // remaining group has not yet processed the empty group
STableListIdInfo idInfo; // this maybe the super table or ordinary table STableListIdInfo idInfo; // this maybe the super table or ordinary table
} STableListInfo; } STableListInfo;

View File

@ -218,9 +218,10 @@ enum {
}; };
typedef enum ETableCountState { typedef enum ETableCountState {
TABLE_COUNT_STATE_NONE = 0, // before start scan TABLE_COUNT_STATE_NONE = 0, // before start scan
TABLE_COUNT_STATE_SCAN = 1, // scanning TABLE_COUNT_STATE_SCAN = 1, // cur group scanning
TABLE_COUNT_STATE_END = 2, // finish or noneed to process TABLE_COUNT_STATE_PROCESSED = 2, // cur group processed
TABLE_COUNT_STATE_END = 3, // finish or noneed to process
} ETableCountState; } ETableCountState;
typedef struct SAggSupporter { typedef struct SAggSupporter {

View File

@ -456,7 +456,7 @@ static void genTbGroupDigest(const SNode* pGroup, uint8_t* filterDigest, T_MD5_C
} }
int32_t getColInfoResultForGroupby(void* pVnode, SNodeList* group, STableListInfo* pTableListInfo, uint8_t* digest, int32_t getColInfoResultForGroupby(void* pVnode, SNodeList* group, STableListInfo* pTableListInfo, uint8_t* digest,
SStorageAPI* pAPI) { SStorageAPI* pAPI, bool initRemainGroups) {
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
SArray* pBlockList = NULL; SArray* pBlockList = NULL;
SSDataBlock* pResBlock = NULL; SSDataBlock* pResBlock = NULL;
@ -590,6 +590,15 @@ int32_t getColInfoResultForGroupby(void* pVnode, SNodeList* group, STableListInf
goto end; goto end;
} }
if (initRemainGroups) {
pTableListInfo->remainGroups =
taosHashInit(rows, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
if (pTableListInfo->remainGroups == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
goto end;
}
}
for (int i = 0; i < rows; i++) { for (int i = 0; i < rows; i++) {
STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i); STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
@ -631,6 +640,14 @@ int32_t getColInfoResultForGroupby(void* pVnode, SNodeList* group, STableListInf
int32_t len = (int32_t)(pStart - (char*)keyBuf); int32_t len = (int32_t)(pStart - (char*)keyBuf);
info->groupId = calcGroupId(keyBuf, len); info->groupId = calcGroupId(keyBuf, len);
if (initRemainGroups) {
// groupId ~ table uid
taosHashPut(pTableListInfo->remainGroups, &(info->groupId), sizeof(info->groupId), &(info->uid), sizeof(info->uid));
}
}
if (initRemainGroups) {
pTableListInfo->numOfOuputGroups = taosHashGetSize(pTableListInfo->remainGroups);
} }
if (tsTagFilterCache) { if (tsTagFilterCache) {
@ -2025,6 +2042,7 @@ STableListInfo* tableListCreate() {
terrno = TSDB_CODE_OUT_OF_MEMORY; terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL; return NULL;
} }
pListInfo->remainGroups = NULL;
pListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo)); pListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo));
if (pListInfo->pTableList == NULL) { if (pListInfo->pTableList == NULL) {
@ -2054,7 +2072,7 @@ void* tableListDestroy(STableListInfo* pTableListInfo) {
taosMemoryFreeClear(pTableListInfo->groupOffset); taosMemoryFreeClear(pTableListInfo->groupOffset);
taosHashCleanup(pTableListInfo->map); taosHashCleanup(pTableListInfo->map);
taosHashCleanup(pTableListInfo->remainGroups);
pTableListInfo->pTableList = NULL; pTableListInfo->pTableList = NULL;
pTableListInfo->map = NULL; pTableListInfo->map = NULL;
taosMemoryFree(pTableListInfo); taosMemoryFree(pTableListInfo);
@ -2068,6 +2086,7 @@ void tableListClear(STableListInfo* pTableListInfo) {
taosArrayClear(pTableListInfo->pTableList); taosArrayClear(pTableListInfo->pTableList);
taosHashClear(pTableListInfo->map); taosHashClear(pTableListInfo->map);
taosHashClear(pTableListInfo->remainGroups);
taosMemoryFree(pTableListInfo->groupOffset); taosMemoryFree(pTableListInfo->groupOffset);
pTableListInfo->numOfOuputGroups = 1; pTableListInfo->numOfOuputGroups = 1;
pTableListInfo->oneTableForEachGroup = false; pTableListInfo->oneTableForEachGroup = false;
@ -2116,70 +2135,6 @@ static int32_t sortTableGroup(STableListInfo* pTableListInfo) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t arrangeTableGroup(STableListInfo* pTableListInfo) {
int32_t code = TSDB_CODE_SUCCESS;
size_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList);
SArray* pDup = NULL;
SHashObj* pHashObj = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
if (!pHashObj) {
return TSDB_CODE_OUT_OF_MEMORY;
}
int32_t num = 1;
// first: get the number of tables per group
for (int32_t i = 0; i < numOfTables; ++i) {
STableKeyInfo* pInfo = taosArrayGet(pTableListInfo->pTableList, i);
int32_t* pVal = taosHashGet(pHashObj, &pInfo->groupId, sizeof(pInfo->groupId));
// update each group's table count
if (!pVal) {
taosHashPut(pHashObj, &pInfo->groupId, sizeof(pInfo->groupId), &num, sizeof(num));
} else {
(*pVal)++;
}
}
pTableListInfo->numOfOuputGroups = taosHashGetSize(pHashObj);
pTableListInfo->oneTableForEachGroup = (pTableListInfo->numOfOuputGroups == numOfTables);
if (pTableListInfo->numOfOuputGroups > 1 && pTableListInfo->numOfOuputGroups < numOfTables) {
pDup = taosArrayDup(pTableListInfo->pTableList, NULL);
pTableListInfo->groupOffset = taosMemoryMalloc(sizeof(int32_t) * pTableListInfo->numOfOuputGroups);
if (pDup == NULL || pTableListInfo->groupOffset == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
goto _exit;
}
int32_t idx = 0, sum = 0;
void* pIter = taosHashIterate(pHashObj, NULL);
while (pIter != NULL) {
// record each group's offset
pTableListInfo->groupOffset[idx] = sum;
int32_t* pData = (int32_t*)pIter;
sum += *pData;
// change value to record group item's first position
*pData = pTableListInfo->groupOffset[idx++];
pIter = taosHashIterate(pHashObj, pIter);
}
// second: arrange the tables and put the items with same groupId together
STableKeyInfo* pStart = taosArrayGet(pTableListInfo->pTableList, 0);
for (int32_t i = 0; i < numOfTables; ++i) {
STableKeyInfo* pInfo = taosArrayGet(pDup, i);
int32_t* pVal = taosHashGet(pHashObj, &pInfo->groupId, sizeof(pInfo->groupId));
if (*pVal != i) {
pStart[*pVal] = *pInfo;
}
(*pVal)++; // update to next item's position
}
}
_exit:
taosHashCleanup(pHashObj);
taosArrayDestroy(pDup);
if (code != TSDB_CODE_SUCCESS) {
taosMemoryFreeClear(pTableListInfo->groupOffset);
}
return code;
}
int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pHandle, SScanPhysiNode* pScanNode, int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pHandle, SScanPhysiNode* pScanNode,
SNodeList* group, bool groupSort, uint8_t* digest, SStorageAPI* pAPI) { SNodeList* group, bool groupSort, uint8_t* digest, SStorageAPI* pAPI) {
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
@ -2206,19 +2161,21 @@ int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle*
pTableListInfo->numOfOuputGroups = 1; pTableListInfo->numOfOuputGroups = 1;
} }
} else { } else {
code = getColInfoResultForGroupby(pHandle->vnode, group, pTableListInfo, digest, pAPI); bool initRemainGroups = false;
if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanNode)) {
STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pScanNode;
if (pTableScanNode->needCountEmptyTable) {
initRemainGroups = true;
}
}
code = getColInfoResultForGroupby(pHandle->vnode, group, pTableListInfo, digest, pAPI, initRemainGroups);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
return code; return code;
} }
if (groupSort || pScanNode->groupOrderScan) { if (groupSort || pScanNode->groupOrderScan) {
code = sortTableGroup(pTableListInfo); code = sortTableGroup(pTableListInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanNode)) {
STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pScanNode;
if (pTableScanNode->needCountEmptyTable) {
// only put together tables with the same groupid
arrangeTableGroup(pTableListInfo);
}
} }
} }

View File

@ -673,14 +673,7 @@ static void initNextGroupScan(STableScanInfo* pInfo, STableKeyInfo** pKeyInfo, i
pInfo->tableEndIndex = numOfTables - 1; pInfo->tableEndIndex = numOfTables - 1;
} }
} else { } else {
int32_t i = pInfo->tableStartIndex + 1; pInfo->tableEndIndex = numOfTables - 1;
for (; i < numOfTables; ++i) {
STableKeyInfo* pCur = tableListGetInfo(pTableListInfo, i);
if (pCur->groupId != pStart->groupId) {
break;
}
}
pInfo->tableEndIndex = i - 1;
} }
if (!pInfo->needCountEmptyTable) { if (!pInfo->needCountEmptyTable) {
@ -693,6 +686,17 @@ static void initNextGroupScan(STableScanInfo* pInfo, STableKeyInfo** pKeyInfo, i
*size = pInfo->tableEndIndex - pInfo->tableStartIndex + 1; *size = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
} }
void markGroupProcessed(STableScanInfo* pInfo, uint64_t groupId) {
if (pInfo->countState == TABLE_COUNT_STATE_END) {
return;
}
if (pInfo->base.pTableListInfo->oneTableForEachGroup) {
pInfo->countState = TABLE_COUNT_STATE_PROCESSED;
} else {
taosHashRemove(pInfo->base.pTableListInfo->remainGroups, &groupId, sizeof(groupId));
}
}
static SSDataBlock* getOneRowResultBlock(SExecTaskInfo* pTaskInfo, STableScanBase* pBase, SSDataBlock* pBlock, static SSDataBlock* getOneRowResultBlock(SExecTaskInfo* pTaskInfo, STableScanBase* pBase, SSDataBlock* pBlock,
const STableKeyInfo* tbInfo) { const STableKeyInfo* tbInfo) {
blockDataEmpty(pBlock); blockDataEmpty(pBlock);
@ -802,7 +806,7 @@ static SSDataBlock* doGroupedTableScan(SOperatorInfo* pOperator) {
while (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) { while (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
SSDataBlock* p = doTableScanImpl(pOperator); SSDataBlock* p = doTableScanImpl(pOperator);
if (p != NULL) { if (p != NULL) {
pTableScanInfo->countState = TABLE_COUNT_STATE_END; markGroupProcessed(pTableScanInfo, p->info.id.groupId);
return p; return p;
} }
@ -831,7 +835,7 @@ static SSDataBlock* doGroupedTableScan(SOperatorInfo* pOperator) {
while (pTableScanInfo->scanTimes < total) { while (pTableScanInfo->scanTimes < total) {
SSDataBlock* p = doTableScanImpl(pOperator); SSDataBlock* p = doTableScanImpl(pOperator);
if (p != NULL) { if (p != NULL) {
pTableScanInfo->countState = TABLE_COUNT_STATE_END; markGroupProcessed(pTableScanInfo, p->info.id.groupId);
return p; return p;
} }
@ -849,11 +853,30 @@ static SSDataBlock* doGroupedTableScan(SOperatorInfo* pOperator) {
} }
if (pTableScanInfo->countState < TABLE_COUNT_STATE_END) { if (pTableScanInfo->countState < TABLE_COUNT_STATE_END) {
// output once for this group STableListInfo* pTableListInfo = pTableScanInfo->base.pTableListInfo;
if (pTableListInfo->oneTableForEachGroup) { // group by tbname
if (pTableScanInfo->countState < TABLE_COUNT_STATE_PROCESSED) {
pTableScanInfo->countState = TABLE_COUNT_STATE_PROCESSED;
STableKeyInfo* pStart =
(STableKeyInfo*)tableListGetInfo(pTableScanInfo->base.pTableListInfo, pTableScanInfo->tableStartIndex);
return getBlockForEmptyTable(pOperator, pStart);
}
} else { // group by tag
int32_t numOfTables = tableListGetSize(pTableListInfo);
if (pTableScanInfo->tableEndIndex + 1 >= numOfTables) {
// get empty group, mark processed & rm from hash
void* pIte = taosHashIterate(pTableListInfo->remainGroups, NULL);
if (pIte != NULL) {
size_t keySize = 0;
uint64_t* pGroupId = taosHashGetKey(pIte, &keySize);
STableKeyInfo info = {.uid = *(uint64_t*)pIte, .groupId = *pGroupId};
taosHashCancelIterate(pTableListInfo->remainGroups, pIte);
markGroupProcessed(pTableScanInfo, *pGroupId);
return getBlockForEmptyTable(pOperator, &info);
}
}
}
pTableScanInfo->countState = TABLE_COUNT_STATE_END; pTableScanInfo->countState = TABLE_COUNT_STATE_END;
STableKeyInfo* pStart =
(STableKeyInfo*)tableListGetInfo(pTableScanInfo->base.pTableListInfo, pTableScanInfo->tableStartIndex);
return getBlockForEmptyTable(pOperator, pStart);
} }
return NULL; return NULL;