enh: add table group cache
This commit is contained in:
parent
13852f5699
commit
c83367e455
|
@ -59,6 +59,13 @@ struct SMetaCache {
|
||||||
SHashObj* pTableEntry;
|
SHashObj* pTableEntry;
|
||||||
SLRUCache* pUidResCache;
|
SLRUCache* pUidResCache;
|
||||||
} sTagFilterResCache;
|
} sTagFilterResCache;
|
||||||
|
|
||||||
|
struct STbGroupResCache {
|
||||||
|
TdThreadMutex lock;
|
||||||
|
uint32_t accTimes;
|
||||||
|
SHashObj* pTableEntry;
|
||||||
|
SLRUCache* pResCache;
|
||||||
|
} STbGroupResCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void entryCacheClose(SMeta* pMeta) {
|
static void entryCacheClose(SMeta* pMeta) {
|
||||||
|
@ -144,6 +151,25 @@ int32_t metaCacheOpen(SMeta* pMeta) {
|
||||||
taosHashSetFreeFp(pCache->sTagFilterResCache.pTableEntry, freeCacheEntryFp);
|
taosHashSetFreeFp(pCache->sTagFilterResCache.pTableEntry, freeCacheEntryFp);
|
||||||
taosThreadMutexInit(&pCache->sTagFilterResCache.lock, NULL);
|
taosThreadMutexInit(&pCache->sTagFilterResCache.lock, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
pCache->STbGroupResCache.pResCache = taosLRUCacheInit(5 * 1024 * 1024, -1, 0.5);
|
||||||
|
if (pCache->STbGroupResCache.pResCache == NULL) {
|
||||||
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
goto _err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCache->STbGroupResCache.accTimes = 0;
|
||||||
|
pCache->STbGroupResCache.pTableEntry =
|
||||||
|
taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
|
||||||
|
if (pCache->STbGroupResCache.pTableEntry == NULL) {
|
||||||
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
goto _err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosHashSetFreeFp(pCache->STbGroupResCache.pTableEntry, freeCacheEntryFp);
|
||||||
|
taosThreadMutexInit(&pCache->STbGroupResCache.lock, NULL);
|
||||||
|
|
||||||
|
|
||||||
pMeta->pCache = pCache;
|
pMeta->pCache = pCache;
|
||||||
return code;
|
return code;
|
||||||
|
|
||||||
|
@ -165,6 +191,10 @@ void metaCacheClose(SMeta* pMeta) {
|
||||||
taosThreadMutexDestroy(&pMeta->pCache->sTagFilterResCache.lock);
|
taosThreadMutexDestroy(&pMeta->pCache->sTagFilterResCache.lock);
|
||||||
taosHashCleanup(pMeta->pCache->sTagFilterResCache.pTableEntry);
|
taosHashCleanup(pMeta->pCache->sTagFilterResCache.pTableEntry);
|
||||||
|
|
||||||
|
taosLRUCacheCleanup(pMeta->pCache->STbGroupResCache.pResCache);
|
||||||
|
taosThreadMutexDestroy(&pMeta->pCache->STbGroupResCache.lock);
|
||||||
|
taosHashCleanup(pMeta->pCache->STbGroupResCache.pTableEntry);
|
||||||
|
|
||||||
taosMemoryFree(pMeta->pCache);
|
taosMemoryFree(pMeta->pCache);
|
||||||
pMeta->pCache = NULL;
|
pMeta->pCache = NULL;
|
||||||
}
|
}
|
||||||
|
@ -520,7 +550,7 @@ int32_t metaGetCachedTableUidList(SMeta* pMeta, tb_uid_t suid, const uint8_t* pK
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freePayload(const void* key, size_t keyLen, void* value) {
|
static void freeUidCachePayload(const void* key, size_t keyLen, void* value) {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -626,7 +656,7 @@ int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to cache.
|
// add to cache.
|
||||||
taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freePayload, NULL,
|
taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeUidCachePayload, NULL,
|
||||||
TAOS_LRU_PRIORITY_LOW);
|
TAOS_LRU_PRIORITY_LOW);
|
||||||
_end:
|
_end:
|
||||||
taosThreadMutexUnlock(pLock);
|
taosThreadMutexUnlock(pLock);
|
||||||
|
@ -671,3 +701,180 @@ int32_t metaUidCacheClear(SMeta* pMeta, uint64_t suid) {
|
||||||
metaDebug("vgId:%d suid:%"PRId64" cached related tag filter uid list cleared", vgId, suid);
|
metaDebug("vgId:%d suid:%"PRId64" cached related tag filter uid list cleared", vgId, suid);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t metaGetCachedTbGroup(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList) {
|
||||||
|
int32_t vgId = TD_VID(pMeta->pVnode);
|
||||||
|
|
||||||
|
// generate the composed key for LRU cache
|
||||||
|
SLRUCache* pCache = pMeta->pCache->STbGroupResCache.pResCache;
|
||||||
|
SHashObj* pTableMap = pMeta->pCache->STbGroupResCache.pTableEntry;
|
||||||
|
TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
|
||||||
|
|
||||||
|
*pList = NULL;
|
||||||
|
uint64_t key[4];
|
||||||
|
initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen);
|
||||||
|
|
||||||
|
taosThreadMutexLock(pLock);
|
||||||
|
pMeta->pCache->STbGroupResCache.accTimes += 1;
|
||||||
|
|
||||||
|
LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN);
|
||||||
|
if (pHandle == NULL) {
|
||||||
|
taosThreadMutexUnlock(pLock);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
|
||||||
|
if (NULL == pEntry) {
|
||||||
|
metaDebug("suid %" PRIu64 " not in tb group cache", suid);
|
||||||
|
return TSDB_CODE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pList = taosLRUCacheValue(pCache, pHandle);
|
||||||
|
|
||||||
|
(*pEntry)->hitTimes += 1;
|
||||||
|
|
||||||
|
uint32_t acc = pMeta->pCache->STbGroupResCache.accTimes;
|
||||||
|
if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) {
|
||||||
|
metaInfo("vgId:%d tb group cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc, ((double)(*pEntry)->hitTimes) / acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
taosLRUCacheRelease(pCache, pHandle, false);
|
||||||
|
|
||||||
|
// unlock meta
|
||||||
|
taosThreadMutexUnlock(pLock);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void freeTbGroupCachePayload(const void* key, size_t keyLen, void* value) {
|
||||||
|
if (value == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t* p = key;
|
||||||
|
if (keyLen != sizeof(int64_t) * 4) {
|
||||||
|
metaError("tb group key length is invalid, length:%d, expect:%d", (int32_t)keyLen, (int32_t)sizeof(uint64_t) * 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHashObj* pHashObj = (SHashObj*)p[0];
|
||||||
|
|
||||||
|
STagFilterResEntry** pEntry = taosHashGet(pHashObj, &p[1], sizeof(uint64_t));
|
||||||
|
|
||||||
|
if (pEntry != NULL && (*pEntry) != NULL) {
|
||||||
|
int64_t st = taosGetTimestampUs();
|
||||||
|
|
||||||
|
SListIter iter = {0};
|
||||||
|
tdListInitIter((SList*)&((*pEntry)->list), &iter, TD_LIST_FORWARD);
|
||||||
|
|
||||||
|
SListNode* pNode = NULL;
|
||||||
|
while ((pNode = tdListNext(&iter)) != NULL) {
|
||||||
|
uint64_t* digest = (uint64_t*)pNode->data;
|
||||||
|
if (digest[0] == p[2] && digest[1] == p[3]) {
|
||||||
|
void* tmp = tdListPopNode(&((*pEntry)->list), pNode);
|
||||||
|
taosMemoryFree(tmp);
|
||||||
|
|
||||||
|
double el = (taosGetTimestampUs() - st) / 1000.0;
|
||||||
|
metaDebug("clear one item in tb group cache, remain cached item:%d, elapsed time:%.2fms", listNEles(&((*pEntry)->list)),
|
||||||
|
el);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taosArrayDestroy((SArray*)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t metaPutTbGroupToCache(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload,
|
||||||
|
int32_t payloadLen) {
|
||||||
|
int32_t code = 0;
|
||||||
|
int32_t vgId = TD_VID(pMeta->pVnode);
|
||||||
|
|
||||||
|
if (payloadLen > tsTagFilterResCacheSize) {
|
||||||
|
metaDebug("vgId:%d, suid:%" PRIu64
|
||||||
|
" ignore to add to tb group cache, due to payload length %d greater than threshold %d",
|
||||||
|
vgId, suid, payloadLen, tsTagFilterResCacheSize);
|
||||||
|
taosArrayDestroy((SArray*)pPayload);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SLRUCache* pCache = pMeta->pCache->STbGroupResCache.pResCache;
|
||||||
|
SHashObj* pTableEntry = pMeta->pCache->STbGroupResCache.pTableEntry;
|
||||||
|
TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
|
||||||
|
|
||||||
|
uint64_t key[4] = {0};
|
||||||
|
initCacheKey(key, pTableEntry, suid, pKey, keyLen);
|
||||||
|
|
||||||
|
taosThreadMutexLock(pLock);
|
||||||
|
STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
|
||||||
|
if (pEntry == NULL) {
|
||||||
|
code = addNewEntry(pTableEntry, pKey, keyLen, suid);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
goto _end;
|
||||||
|
}
|
||||||
|
} else { // check if it exists or not
|
||||||
|
size_t size = listNEles(&(*pEntry)->list);
|
||||||
|
if (size == 0) {
|
||||||
|
tdListAppend(&(*pEntry)->list, pKey);
|
||||||
|
} else {
|
||||||
|
SListNode* pNode = listHead(&(*pEntry)->list);
|
||||||
|
uint64_t* p = (uint64_t*)pNode->data;
|
||||||
|
if (p[1] == ((uint64_t*)pKey)[1] && p[0] == ((uint64_t*)pKey)[0]) {
|
||||||
|
// we have already found the existed items, no need to added to cache anymore.
|
||||||
|
taosThreadMutexUnlock(pLock);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
} else { // not equal, append it
|
||||||
|
tdListAppend(&(*pEntry)->list, pKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to cache.
|
||||||
|
taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeTbGroupCachePayload, NULL,
|
||||||
|
TAOS_LRU_PRIORITY_LOW);
|
||||||
|
_end:
|
||||||
|
taosThreadMutexUnlock(pLock);
|
||||||
|
metaDebug("vgId:%d, suid:%" PRIu64 " tb group added into cache, total:%d, tables:%d", vgId, suid,
|
||||||
|
(int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry));
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables
|
||||||
|
int32_t metaTbGroupCacheClear(SMeta* pMeta, uint64_t suid) {
|
||||||
|
uint64_t p[4] = {0};
|
||||||
|
int32_t vgId = TD_VID(pMeta->pVnode);
|
||||||
|
SHashObj* pEntryHashMap = pMeta->pCache->STbGroupResCache.pTableEntry;
|
||||||
|
|
||||||
|
uint64_t dummy[2] = {0};
|
||||||
|
initCacheKey(p, pEntryHashMap, suid, (char*) &dummy[0], 16);
|
||||||
|
|
||||||
|
TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
|
||||||
|
taosThreadMutexLock(pLock);
|
||||||
|
|
||||||
|
STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
|
||||||
|
if (pEntry == NULL || listNEles(&(*pEntry)->list) == 0) {
|
||||||
|
taosThreadMutexUnlock(pLock);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*pEntry)->hitTimes = 0;
|
||||||
|
|
||||||
|
SListIter iter = {0};
|
||||||
|
tdListInitIter(&(*pEntry)->list, &iter, TD_LIST_FORWARD);
|
||||||
|
|
||||||
|
SListNode* pNode = NULL;
|
||||||
|
while ((pNode = tdListNext(&iter)) != NULL) {
|
||||||
|
setMD5DigestInKey(p, pNode->data, 2 * sizeof(uint64_t));
|
||||||
|
taosLRUCacheErase(pMeta->pCache->STbGroupResCache.pResCache, p, TAG_FILTER_RES_KEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
tdListEmpty(&(*pEntry)->list);
|
||||||
|
taosThreadMutexUnlock(pLock);
|
||||||
|
|
||||||
|
metaDebug("vgId:%d suid:%"PRId64" cached related tb group cleared", vgId, suid);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -767,6 +767,7 @@ int metaCreateTable(SMeta *pMeta, int64_t version, SVCreateTbReq *pReq, STableMe
|
||||||
metaWLock(pMeta);
|
metaWLock(pMeta);
|
||||||
metaUpdateStbStats(pMeta, me.ctbEntry.suid, 1);
|
metaUpdateStbStats(pMeta, me.ctbEntry.suid, 1);
|
||||||
metaUidCacheClear(pMeta, me.ctbEntry.suid);
|
metaUidCacheClear(pMeta, me.ctbEntry.suid);
|
||||||
|
metaTbGroupCacheClear(pMeta, me.ctbEntry.suid);
|
||||||
metaULock(pMeta);
|
metaULock(pMeta);
|
||||||
} else {
|
} else {
|
||||||
me.ntbEntry.ctime = pReq->ctime;
|
me.ntbEntry.ctime = pReq->ctime;
|
||||||
|
@ -999,6 +1000,7 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
|
||||||
|
|
||||||
metaUpdateStbStats(pMeta, e.ctbEntry.suid, -1);
|
metaUpdateStbStats(pMeta, e.ctbEntry.suid, -1);
|
||||||
metaUidCacheClear(pMeta, e.ctbEntry.suid);
|
metaUidCacheClear(pMeta, e.ctbEntry.suid);
|
||||||
|
metaTbGroupCacheClear(pMeta, e.ctbEntry.suid);
|
||||||
} else if (e.type == TSDB_NORMAL_TABLE) {
|
} else if (e.type == TSDB_NORMAL_TABLE) {
|
||||||
// drop schema.db (todo)
|
// drop schema.db (todo)
|
||||||
|
|
||||||
|
@ -1010,6 +1012,7 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
|
||||||
|
|
||||||
metaStatsCacheDrop(pMeta, uid);
|
metaStatsCacheDrop(pMeta, uid);
|
||||||
metaUidCacheClear(pMeta, uid);
|
metaUidCacheClear(pMeta, uid);
|
||||||
|
metaTbGroupCacheClear(pMeta, uid);
|
||||||
--pMeta->pVnode->config.vndStats.numOfSTables;
|
--pMeta->pVnode->config.vndStats.numOfSTables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1430,6 +1433,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
|
||||||
((STag *)(ctbEntry.ctbEntry.pTags))->len, pMeta->txn);
|
((STag *)(ctbEntry.ctbEntry.pTags))->len, pMeta->txn);
|
||||||
|
|
||||||
metaUidCacheClear(pMeta, ctbEntry.ctbEntry.suid);
|
metaUidCacheClear(pMeta, ctbEntry.ctbEntry.suid);
|
||||||
|
metaTbGroupCacheClear(pMeta, ctbEntry.ctbEntry.suid);
|
||||||
|
|
||||||
metaULock(pMeta);
|
metaULock(pMeta);
|
||||||
|
|
||||||
|
|
|
@ -454,15 +454,14 @@ static void genTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32_t getColInfoResultForGroupby(void* metaHandle, uint64_t suid, SNodeList* group, STableListInfo* pTableListInfo) {
|
int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableListInfo* pTableListInfo) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
SArray* pBlockList = NULL;
|
SArray* pBlockList = NULL;
|
||||||
SSDataBlock* pResBlock = NULL;
|
SSDataBlock* pResBlock = NULL;
|
||||||
void* keyBuf = NULL;
|
void* keyBuf = NULL;
|
||||||
SArray* groupData = NULL;
|
SArray* groupData = NULL;
|
||||||
SArray* pUidTagList = NULL;
|
SArray* pUidTagList = NULL;
|
||||||
static T_MD5_CTX lastMd5 = {-1};
|
SArray* tableList = NULL;
|
||||||
static SArray* lastTableList = NULL;
|
|
||||||
static SHashObj *pTableListHash = NULL;
|
static SHashObj *pTableListHash = NULL;
|
||||||
|
|
||||||
int32_t rows = taosArrayGetSize(pTableListInfo->pTableList);
|
int32_t rows = taosArrayGetSize(pTableListInfo->pTableList);
|
||||||
|
@ -498,10 +497,10 @@ int32_t getColInfoResultForGroupby(void* metaHandle, uint64_t suid, SNodeList* g
|
||||||
|
|
||||||
SArray **pLastTableList = (SArray **)taosHashGet(pTableListHash, context.digest, sizeof(context.digest));
|
SArray **pLastTableList = (SArray **)taosHashGet(pTableListHash, context.digest, sizeof(context.digest));
|
||||||
if (pLastTableList && *pLastTableList) {
|
if (pLastTableList && *pLastTableList) {
|
||||||
pTableListInfo->pTableList = taosArrayDup(lastTableList, NULL);
|
pTableListInfo->pTableList = taosArrayDup(*pLastTableList, NULL);
|
||||||
goto end;
|
goto end;
|
||||||
} else {
|
} else {
|
||||||
qError("group not hit, last:%p, lastSize:%d, newSize:%d", lastTableList, (int32_t)taosArrayGetSize(lastTableList), (int32_t)taosArrayGetSize(pTableListInfo->pTableList));
|
qError("group not hit");
|
||||||
}
|
}
|
||||||
|
|
||||||
pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo));
|
pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo));
|
||||||
|
@ -637,8 +636,8 @@ int32_t getColInfoResultForGroupby(void* metaHandle, uint64_t suid, SNodeList* g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTableList = taosArrayDup(pTableListInfo->pTableList, NULL);
|
tableList = taosArrayDup(pTableListInfo->pTableList, NULL);
|
||||||
taosHashPut(pTableListHash, context.digest, sizeof(context.digest), &lastTableList, POINTER_BYTES);
|
taosHashPut(pTableListHash, context.digest, sizeof(context.digest), &tableList, POINTER_BYTES);
|
||||||
|
|
||||||
// int64_t st2 = taosGetTimestampUs();
|
// int64_t st2 = taosGetTimestampUs();
|
||||||
// qDebug("calculate tag block rows:%d, cost:%ld us", rows, st2-st1);
|
// qDebug("calculate tag block rows:%d, cost:%ld us", rows, st2-st1);
|
||||||
|
@ -2046,7 +2045,7 @@ int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle*
|
||||||
pTableListInfo->numOfOuputGroups = 1;
|
pTableListInfo->numOfOuputGroups = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code = getColInfoResultForGroupby(pHandle->meta, pScanNode->suid, group, pTableListInfo);
|
code = getColInfoResultForGroupby(pHandle->meta, group, pTableListInfo);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue