提交 7d00b7a6 编写于 作者: H Haojun Liao

refactor: add tag filter cache.

上级 ba5244d1
...@@ -44,6 +44,8 @@ extern int32_t tsCompatibleModel; ...@@ -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); ...@@ -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; ...@@ -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); ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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: ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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,19 +973,47 @@ int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, ...@@ -973,19 +973,47 @@ 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) { if (pTagIndexCond) {
SIndexMetaArg metaArg = { char* payload = NULL;
.metaEx = metaHandle, .idx = tsdbGetIdx(metaHandle), .ivtIdx = tsdbGetIvtIdx(metaHandle), .suid = tableUid}; int32_t len = 0;
nodesNodeToMsg(pTagCond, &payload, &len);
// int64_t stt = taosGetTimestampUs();
SIdxFltStatus status = SFLT_NOT_INDEX; tMD5Init(&context);
code = doFilterTag(pTagIndexCond, &metaArg, res, &status); tMD5Update(&context, (uint8_t*)payload, (uint32_t)len);
if (code != 0 || status == SFLT_NOT_INDEX) { tMD5Final(&context);
qError("failed to get tableIds from index, reason:%s, suid:%" PRIu64, tstrerror(code), tableUid); }
code = TDB_CODE_SUCCESS;
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) {
SIndexMetaArg metaArg = {
.metaEx = metaHandle, .idx = tsdbGetIdx(metaHandle), .ivtIdx = tsdbGetIvtIdx(metaHandle), .suid = tableUid};
SIdxFltStatus status = SFLT_NOT_INDEX;
code = doFilterTag(pTagIndexCond, &metaArg, res, &status);
if (code != 0 || status == SFLT_NOT_INDEX) {
qError("failed to get tableIds from index, reason:%s, suid:%" PRIu64, tstrerror(code), tableUid);
code = TDB_CODE_SUCCESS;
}
} else if (!pTagCond) {
vnodeGetCtbIdList(pVnode, pScanNode->suid, res);
} }
} else if (!pTagCond) {
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)) {
......
...@@ -60,7 +60,7 @@ int32_t tdListPrepend(SList *list, void *data) { ...@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册