refactor: add tag filter cache.
This commit is contained in:
parent
ba5244d1b6
commit
7d00b7a6c4
|
@ -44,6 +44,8 @@ extern int32_t tsCompatibleModel;
|
||||||
extern bool tsPrintAuth;
|
extern bool tsPrintAuth;
|
||||||
extern int64_t tsTickPerMin[3];
|
extern int64_t tsTickPerMin[3];
|
||||||
extern int32_t tsCountAlwaysReturnValue;
|
extern int32_t tsCountAlwaysReturnValue;
|
||||||
|
extern float tsSelectivityRatio;
|
||||||
|
extern int32_t tsTagFilterResCacheSize;
|
||||||
|
|
||||||
// queue & threads
|
// queue & threads
|
||||||
extern int32_t tsNumOfRpcThreads;
|
extern int32_t tsNumOfRpcThreads;
|
||||||
|
|
|
@ -225,7 +225,7 @@ void *tdListFree(SList *list);
|
||||||
void tdListPrependNode(SList *list, SListNode *node);
|
void tdListPrependNode(SList *list, SListNode *node);
|
||||||
void tdListAppendNode(SList *list, SListNode *node);
|
void tdListAppendNode(SList *list, SListNode *node);
|
||||||
int32_t tdListPrepend(SList *list, void *data);
|
int32_t tdListPrepend(SList *list, void *data);
|
||||||
int32_t tdListAppend(SList *list, void *data);
|
int32_t tdListAppend(SList *list, const void *data);
|
||||||
SListNode *tdListPopHead(SList *list);
|
SListNode *tdListPopHead(SList *list);
|
||||||
SListNode *tdListPopTail(SList *list);
|
SListNode *tdListPopTail(SList *list);
|
||||||
SListNode *tdListGetHead(SList *list);
|
SListNode *tdListGetHead(SList *list);
|
||||||
|
|
|
@ -119,6 +119,9 @@ int32_t tsMinIntervalTime = 1;
|
||||||
// maximum memory allowed to be allocated for a single csv load (in MB)
|
// maximum memory allowed to be allocated for a single csv load (in MB)
|
||||||
int32_t tsMaxMemUsedByInsert = 1024;
|
int32_t tsMaxMemUsedByInsert = 1024;
|
||||||
|
|
||||||
|
float tsSelectivityRatio = 1.0;
|
||||||
|
int32_t tsTagFilterResCacheSize = 4096;
|
||||||
|
|
||||||
// the maximum allowed query buffer size during query processing for each data node.
|
// the maximum allowed query buffer size during query processing for each data node.
|
||||||
// -1 no limit (default)
|
// -1 no limit (default)
|
||||||
// 0 no query allowed, queries are disabled
|
// 0 no query allowed, queries are disabled
|
||||||
|
|
|
@ -108,6 +108,9 @@ int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName);
|
||||||
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid);
|
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid);
|
||||||
int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType);
|
int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType);
|
||||||
bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid);
|
bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid);
|
||||||
|
int32_t metaGetCachedTableUidList(SMeta *pMeta, tb_uid_t suid, const uint8_t *key, int32_t keyLen, SArray *pList, bool* acquired);
|
||||||
|
int32_t metaUidFilterCachePut(SMeta *pMeta, uint64_t suid, const void *pKey, int32_t keyLen, void *pPayload,
|
||||||
|
int32_t payloadLen, double selectivityRatio);
|
||||||
|
|
||||||
typedef struct SMetaFltParam {
|
typedef struct SMetaFltParam {
|
||||||
tb_uid_t suid;
|
tb_uid_t suid;
|
||||||
|
|
|
@ -33,7 +33,7 @@ typedef struct SMetaStbStatsEntry {
|
||||||
|
|
||||||
typedef struct STagFilterResEntry {
|
typedef struct STagFilterResEntry {
|
||||||
uint64_t suid; // uid for super table
|
uint64_t suid; // uid for super table
|
||||||
SList* pList; // the linked list of md5 digest, extracted from the serialized tag query condition
|
SList list; // the linked list of md5 digest, extracted from the serialized tag query condition
|
||||||
uint32_t qTimes;// queried times for current super table
|
uint32_t qTimes;// queried times for current super table
|
||||||
} STagFilterResEntry;
|
} STagFilterResEntry;
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ struct SMetaCache {
|
||||||
struct STagFilterResCache {
|
struct STagFilterResCache {
|
||||||
SHashObj* pTableEntry;
|
SHashObj* pTableEntry;
|
||||||
SLRUCache* pUidResCache;
|
SLRUCache* pUidResCache;
|
||||||
|
uint64_t keyBuf[3];
|
||||||
} sTagFilterResCache;
|
} sTagFilterResCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,9 +120,19 @@ int32_t metaCacheOpen(SMeta* pMeta) {
|
||||||
goto _err2;
|
goto _err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pMeta->pCache = pCache;
|
pCache->sTagFilterResCache.pUidResCache = taosLRUCacheInit(5*1024*1024, -1, 0.5);
|
||||||
|
if (pCache->sTagFilterResCache.pUidResCache == NULL) {
|
||||||
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
goto _err2;
|
||||||
|
}
|
||||||
|
|
||||||
_exit:
|
pCache->sTagFilterResCache.pTableEntry = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
|
||||||
|
if (pCache->sTagFilterResCache.pTableEntry == NULL) {
|
||||||
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
goto _err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pMeta->pCache = pCache;
|
||||||
return code;
|
return code;
|
||||||
|
|
||||||
_err2:
|
_err2:
|
||||||
|
@ -129,7 +140,6 @@ _err2:
|
||||||
|
|
||||||
_err:
|
_err:
|
||||||
taosMemoryFree(pCache);
|
taosMemoryFree(pCache);
|
||||||
|
|
||||||
metaError("vgId:%d, meta open cache failed since %s", TD_VID(pMeta->pVnode), tstrerror(code));
|
metaError("vgId:%d, meta open cache failed since %s", TD_VID(pMeta->pVnode), tstrerror(code));
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +148,11 @@ void metaCacheClose(SMeta* pMeta) {
|
||||||
if (pMeta->pCache) {
|
if (pMeta->pCache) {
|
||||||
entryCacheClose(pMeta);
|
entryCacheClose(pMeta);
|
||||||
statsCacheClose(pMeta);
|
statsCacheClose(pMeta);
|
||||||
|
|
||||||
|
taosHashCleanup(pMeta->pCache->sTagFilterResCache.pTableEntry);
|
||||||
|
taosLRUCacheCleanup(pMeta->pCache->sTagFilterResCache.pUidResCache);
|
||||||
|
|
||||||
|
taosMemoryFree(pMeta->pCache->sTagFilterResCache.keyBuf);
|
||||||
taosMemoryFree(pMeta->pCache);
|
taosMemoryFree(pMeta->pCache);
|
||||||
pMeta->pCache = NULL;
|
pMeta->pCache = NULL;
|
||||||
}
|
}
|
||||||
|
@ -399,38 +414,48 @@ int32_t metaStatsCacheGet(SMeta* pMeta, int64_t uid, SMetaStbStats* pInfo) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t metaUidFilterCacheGet(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, LRUHandle** pHandle) {
|
int32_t metaGetCachedTableUidList(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray* pList1, bool* acquireRes) {
|
||||||
|
uint64_t* pBuf = pMeta->pCache->sTagFilterResCache.keyBuf;
|
||||||
|
|
||||||
// generate the composed key for LRU cache
|
// generate the composed key for LRU cache
|
||||||
char* p = taosMemoryMalloc(keyLen + sizeof(uint64_t));
|
SLRUCache* pCache = pMeta->pCache->sTagFilterResCache.pUidResCache;
|
||||||
*(uint64_t*) p = suid;
|
|
||||||
memcpy(p + sizeof(suid), pKey, keyLen);
|
pBuf[0] = suid;
|
||||||
|
memcpy(&pBuf[1], pKey, keyLen);
|
||||||
|
|
||||||
int32_t len = keyLen + sizeof(uint64_t);
|
int32_t len = keyLen + sizeof(uint64_t);
|
||||||
*pHandle = taosLRUCacheLookup(pMeta->pCache->sTagFilterResCache.pUidResCache, p, len);
|
LRUHandle *pHandle = taosLRUCacheLookup(pCache, pBuf, len);
|
||||||
if (*pHandle == NULL) {
|
if (pHandle == NULL) {
|
||||||
taosMemoryFree(p);
|
*acquireRes = 0;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
} else { // do some book mark work after acquiring the filter result from cache
|
} else { // do some book mark work after acquiring the filter result from cache
|
||||||
STagFilterResEntry* pEntry = taosHashGet(pMeta->pCache->sTagFilterResCache.pTableEntry, &suid, sizeof(uint64_t));
|
STagFilterResEntry* pEntry = taosHashGet(pMeta->pCache->sTagFilterResCache.pTableEntry, &suid, sizeof(uint64_t));
|
||||||
ASSERT(pEntry != NULL);
|
ASSERT(pEntry != NULL);
|
||||||
|
*acquireRes = 1;
|
||||||
|
|
||||||
|
const char* p = taosLRUCacheValue(pMeta->pCache->sTagFilterResCache.pUidResCache, pHandle);
|
||||||
|
int32_t size = *(int32_t*) p;
|
||||||
|
taosArrayAddBatch(pList1, p + sizeof(int32_t), size);
|
||||||
|
|
||||||
pEntry->qTimes += 1;
|
pEntry->qTimes += 1;
|
||||||
|
|
||||||
// check if scanning all items are necessary or not
|
// check if scanning all items are necessary or not
|
||||||
if (pEntry->qTimes > 5000 && TD_DLIST_NELES(pEntry->pList) > 10) {
|
if (pEntry->qTimes >= 5000 && TD_DLIST_NELES(&pEntry->list) > 10) {
|
||||||
SArray* pList = taosArrayInit(64, POINTER_BYTES);
|
SArray* pList = taosArrayInit(64, POINTER_BYTES);
|
||||||
|
|
||||||
SListIter iter = {0};
|
SListIter iter = {0};
|
||||||
tdListInitIter(pEntry->pList, &iter, TD_LIST_FORWARD);
|
tdListInitIter(&pEntry->list, &iter, TD_LIST_FORWARD);
|
||||||
|
|
||||||
SListNode* pNode = NULL;
|
SListNode* pNode = NULL;
|
||||||
while ((pNode = tdListNext(&iter)) != NULL) {
|
while ((pNode = tdListNext(&iter)) != NULL) {
|
||||||
memcpy(p + sizeof(suid), pNode->data, keyLen);
|
memcpy(pBuf + sizeof(suid), pNode->data, keyLen);
|
||||||
|
|
||||||
// check whether it is existed in LRU cache, and remove it from linked list if not.
|
// check whether it is existed in LRU cache, and remove it from linked list if not.
|
||||||
void* pRes = taosLRUCacheLookup(pMeta->pCache->sTagFilterResCache.pUidResCache, p, len);
|
LRUHandle* pRes = taosLRUCacheLookup(pCache, pBuf, len);
|
||||||
if (pRes == NULL) { // remove the item in the linked list
|
if (pRes == NULL) { // remove the item in the linked list
|
||||||
taosArrayPush(pList, &pNode);
|
taosArrayPush(pList, &pNode);
|
||||||
|
} else {
|
||||||
|
taosLRUCacheRelease(pCache, pRes, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,19 +463,49 @@ int32_t metaUidFilterCacheGet(SMeta* pMeta, uint64_t suid, const void* pKey, int
|
||||||
size_t s = taosArrayGetSize(pList);
|
size_t s = taosArrayGetSize(pList);
|
||||||
for(int32_t i = 0; i < s; ++i) {
|
for(int32_t i = 0; i < s; ++i) {
|
||||||
SListNode** p1 = taosArrayGet(pList, i);
|
SListNode** p1 = taosArrayGet(pList, i);
|
||||||
tdListPopNode(pEntry->pList, *p1);
|
tdListPopNode(&pEntry->list, *p1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
taosMemoryFree(p);
|
pEntry->qTimes = 0; // reset the query times
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check both the payload size and selectivity ratio
|
// check both the payload size and selectivity ratio
|
||||||
int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload) {
|
int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, int32_t payloadLen, double selectivityRatio) {
|
||||||
|
if (selectivityRatio > tsSelectivityRatio) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadLen > tsTagFilterResCacheSize) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SLRUCache* pCache = pMeta->pCache->sTagFilterResCache.pUidResCache;
|
||||||
|
SHashObj* pTableEntry = pMeta->pCache->sTagFilterResCache.pTableEntry;
|
||||||
|
|
||||||
|
void* pEntry = taosHashGet(pMeta->pCache->sTagFilterResCache.pTableEntry, &suid, sizeof(uint64_t));
|
||||||
|
if (pEntry == NULL) {
|
||||||
|
STagFilterResEntry* p = taosMemoryMalloc(sizeof(STagFilterResEntry));
|
||||||
|
p->qTimes = 0;
|
||||||
|
tdListInit(&p->list, keyLen);
|
||||||
|
taosHashPut(pTableEntry, &suid, sizeof(uint64_t), pEntry, POINTER_BYTES);
|
||||||
|
|
||||||
|
pEntry = &p;
|
||||||
|
}
|
||||||
|
|
||||||
|
tdListAppend(&(*(STagFilterResEntry**)pEntry)->list, pKey);
|
||||||
|
|
||||||
|
uint64_t* pBuf = pMeta->pCache->sTagFilterResCache.keyBuf;
|
||||||
|
pBuf[0] = suid;
|
||||||
|
|
||||||
|
memcpy(&pBuf[1], pKey, keyLen);
|
||||||
|
ASSERT(sizeof(uint64_t) + keyLen == 24);
|
||||||
|
|
||||||
|
// add to cache.
|
||||||
|
taosLRUCacheInsert(pCache, pBuf, sizeof(uint64_t) + keyLen, pPayload, payloadLen, NULL, NULL, TAOS_LRU_PRIORITY_LOW);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +521,7 @@ int32_t metaUidCacheClear(SMeta* pMeta, uint64_t suid) {
|
||||||
*(uint64_t*)p = pEntry->suid;
|
*(uint64_t*)p = pEntry->suid;
|
||||||
|
|
||||||
SListIter iter = {0};
|
SListIter iter = {0};
|
||||||
tdListInitIter(pEntry->pList, &iter, TD_LIST_FORWARD);
|
tdListInitIter(&pEntry->list, &iter, TD_LIST_FORWARD);
|
||||||
|
|
||||||
SListNode* pNode = NULL;
|
SListNode* pNode = NULL;
|
||||||
while ((pNode = tdListNext(&iter)) != NULL) {
|
while ((pNode = tdListNext(&iter)) != NULL) {
|
||||||
|
@ -474,6 +529,8 @@ int32_t metaUidCacheClear(SMeta* pMeta, uint64_t suid) {
|
||||||
taosLRUCacheErase(pMeta->pCache->sTagFilterResCache.pUidResCache, p, keyLen);
|
taosLRUCacheErase(pMeta->pCache->sTagFilterResCache.pUidResCache, p, keyLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pEntry->qTimes = 0;
|
||||||
|
tdListEmpty(&pEntry->list);
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -973,11 +973,28 @@ int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode,
|
||||||
SArray* res = taosArrayInit(8, sizeof(uint64_t));
|
SArray* res = taosArrayInit(8, sizeof(uint64_t));
|
||||||
|
|
||||||
if (pScanNode->tableType == TSDB_SUPER_TABLE) {
|
if (pScanNode->tableType == TSDB_SUPER_TABLE) {
|
||||||
|
// try to retrieve the result from meta cache
|
||||||
|
// generate the cache key
|
||||||
|
T_MD5_CTX context = {0};
|
||||||
|
|
||||||
|
if (pTagIndexCond) {
|
||||||
|
char* payload = NULL;
|
||||||
|
int32_t len = 0;
|
||||||
|
nodesNodeToMsg(pTagCond, &payload, &len);
|
||||||
|
|
||||||
|
tMD5Init(&context);
|
||||||
|
tMD5Update(&context, (uint8_t*)payload, (uint32_t)len);
|
||||||
|
tMD5Final(&context);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool acquired = false;
|
||||||
|
metaGetCachedTableUidList(metaHandle, pScanNode->suid, context.digest, tListLen(context.digest), res, &acquired);
|
||||||
|
if (!acquired) {
|
||||||
|
// failed to find the result in the cache, let try to calculate the results
|
||||||
if (pTagIndexCond) {
|
if (pTagIndexCond) {
|
||||||
SIndexMetaArg metaArg = {
|
SIndexMetaArg metaArg = {
|
||||||
.metaEx = metaHandle, .idx = tsdbGetIdx(metaHandle), .ivtIdx = tsdbGetIvtIdx(metaHandle), .suid = tableUid};
|
.metaEx = metaHandle, .idx = tsdbGetIdx(metaHandle), .ivtIdx = tsdbGetIvtIdx(metaHandle), .suid = tableUid};
|
||||||
|
|
||||||
// int64_t stt = taosGetTimestampUs();
|
|
||||||
SIdxFltStatus status = SFLT_NOT_INDEX;
|
SIdxFltStatus status = SFLT_NOT_INDEX;
|
||||||
code = doFilterTag(pTagIndexCond, &metaArg, res, &status);
|
code = doFilterTag(pTagIndexCond, &metaArg, res, &status);
|
||||||
if (code != 0 || status == SFLT_NOT_INDEX) {
|
if (code != 0 || status == SFLT_NOT_INDEX) {
|
||||||
|
@ -987,6 +1004,17 @@ int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode,
|
||||||
} else if (!pTagCond) {
|
} else if (!pTagCond) {
|
||||||
vnodeGetCtbIdList(pVnode, pScanNode->suid, res);
|
vnodeGetCtbIdList(pVnode, pScanNode->suid, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let's add the filter results into meta-cache
|
||||||
|
size_t numOfTables = taosArrayGetSize(res);
|
||||||
|
size_t size = numOfTables * sizeof(uint64_t) + sizeof(int32_t);
|
||||||
|
char* pPayload = taosMemoryMalloc(size);
|
||||||
|
*(int32_t*)pPayload = numOfTables;
|
||||||
|
memcpy(pPayload + sizeof(int32_t), taosArrayGet(res, 0), numOfTables * sizeof(uint64_t));
|
||||||
|
|
||||||
|
metaUidFilterCachePut(metaHandle, pScanNode->suid, context.digest, tListLen(context.digest), pPayload,
|
||||||
|
size, 1);
|
||||||
|
}
|
||||||
} else { // Create one table group.
|
} else { // Create one table group.
|
||||||
if (metaIsTableExist(metaHandle, tableUid)) {
|
if (metaIsTableExist(metaHandle, tableUid)) {
|
||||||
taosArrayPush(res, &tableUid);
|
taosArrayPush(res, &tableUid);
|
||||||
|
|
|
@ -60,7 +60,7 @@ int32_t tdListPrepend(SList *list, void *data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tdListAppend(SList *list, void *data) {
|
int32_t tdListAppend(SList *list, const void *data) {
|
||||||
SListNode *node = (SListNode *)taosMemoryCalloc(1, sizeof(SListNode) + list->eleSize);
|
SListNode *node = (SListNode *)taosMemoryCalloc(1, sizeof(SListNode) + list->eleSize);
|
||||||
if (node == NULL) return -1;
|
if (node == NULL) return -1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue