Avoid allocating hypertable cache storage for negative entries.

The hypertable cache stores negative cache entries to speed up checks
for tables that aren't hypertables. However, a full hypertable cache
entry was allocated for these negative entries, thus wasting cache
storage. With this update, the full entry is only allocated for
positive entries that actually represent hypertables.
This commit is contained in:
Erik Nordström 2017-03-14 11:20:23 +01:00
parent a1da9bf5c5
commit 852ba7ee97
2 changed files with 39 additions and 46 deletions

View File

@ -17,18 +17,18 @@
#include "scanner.h"
#include "partitioning.h"
static void *hypertable_cache_create_entry(Cache *cache, CacheQueryCtx *ctx);
static void *hypertable_cache_create_entry(Cache * cache, CacheQueryCtx * ctx);
typedef struct HypertableCacheQueryCtx
{
CacheQueryCtx cctx;
Oid main_table_relid;
char *schema;
char *table_name;
} HypertableCacheQueryCtx;
const char *schema;
const char *table;
} HypertableCacheQueryCtx;
static void *
hypertable_cache_get_key(CacheQueryCtx *ctx)
hypertable_cache_get_key(CacheQueryCtx * ctx)
{
return &((HypertableCacheQueryCtx *) ctx)->main_table_relid;
}
@ -36,9 +36,8 @@ hypertable_cache_get_key(CacheQueryCtx *ctx)
typedef struct
{
Oid main_table_relid;
bool negative; /* true if no such hypertable exists */
Hypertable entry;
} HypertableNameCacheEntry;
Hypertable *hypertable;
} HypertableNameCacheEntry;
static Cache *
@ -77,15 +76,18 @@ static Cache *hypertable_cache_current = NULL;
/* Column numbers for 'hypertable' table in sql/common/tables.sql */
static bool
hypertable_tuple_found(TupleInfo *ti, void *data)
hypertable_tuple_found(TupleInfo * ti, void *data)
{
Hypertable *he = data;
HypertableNameCacheEntry *entry = data;
Hypertable *he;
Datum values[Natts_hypertable];
bool isnull[Natts_hypertable];
char *root_table_name;
char *root_table_schema;
int32 id;
he = palloc(sizeof(Hypertable));
heap_deform_tuple(ti->tuple, ti->desc, values, isnull);
id = DatumGetInt32(DATUM_GET(values, Anum_hypertable_id));
@ -109,58 +111,58 @@ hypertable_tuple_found(TupleInfo *ti, void *data)
he->chunk_size_bytes = DatumGetInt64(DATUM_GET(values, Anum_hypertable_chunk_size_bytes));
he->num_replicas = DatumGetInt16(DATUM_GET(values, Anum_hypertable_replication_factor));
entry->hypertable = he;
return false;
}
static void *
hypertable_cache_create_entry(Cache *cache, CacheQueryCtx *ctx)
hypertable_cache_create_entry(Cache * cache, CacheQueryCtx * ctx)
{
HypertableCacheQueryCtx *hctx = (HypertableCacheQueryCtx *) ctx;
Catalog *catalog = catalog_get();
HypertableNameCacheEntry *cache_entry = hctx->cctx.entry;
Hypertable *he = &cache_entry->entry;
HypertableNameCacheEntry *cache_entry = ctx->entry;
int number_found;
char *schema = hctx->schema;
char *table_name = hctx->table_name;
ScanKeyData scankey[2];
ScannerCtx scanCtx = {
.table = catalog->tables[HYPERTABLE].id,
.index = catalog->tables[HYPERTABLE].index_ids[HYPERTABLE_NAME_INDEX],
.scantype = ScannerTypeIndex,
.nkeys = 2,
.scankey = scankey,
.data = he,
.data = ctx->entry,
.tuple_found = hypertable_tuple_found,
.lockmode = AccessShareLock,
.scandirection = ForwardScanDirection,
};
if (NULL == schema)
if (NULL == hctx->schema)
{
schema = get_namespace_name(get_rel_namespace(hctx->main_table_relid));
hctx->schema = get_namespace_name(get_rel_namespace(hctx->main_table_relid));
}
if (NULL == table_name)
if (NULL == hctx->table)
{
table_name = get_rel_name(hctx->main_table_relid);
hctx->table = get_rel_name(hctx->main_table_relid);
}
/* Perform an index scan on schema and table. */
ScanKeyInit(&scankey[0], Anum_hypertable_name_idx_schema,
BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(schema));
BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(hctx->schema));
ScanKeyInit(&scankey[1], Anum_hypertable_name_idx_table,
BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(table_name));
BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(hctx->table));
number_found = scanner_scan(&scanCtx);
switch (number_found)
{
case 0:
cache_entry->negative = true;
/* Negative cache entry: table is not a hypertable */
cache_entry->hypertable = NULL;
break;
case 1:
cache_entry->negative = false;
Assert(strncmp(he->schema, get_namespace_name(get_rel_namespace(hctx->main_table_relid)), NAMEDATALEN) == 0);
Assert(strncmp(he->table, get_rel_name(hctx->main_table_relid), NAMEDATALEN) == 0);
Assert(strncmp(cache_entry->hypertable->schema, hctx->schema, NAMEDATALEN) == 0);
Assert(strncmp(cache_entry->hypertable->table, hctx->table, NAMEDATALEN) == 0);
break;
default:
elog(ERROR, "Got an unexpected number of records: %d", number_found);
@ -180,30 +182,22 @@ hypertable_cache_invalidate_callback(void)
/* Get hypertable cache entry. If the entry is not in the cache, add it. */
Hypertable *
hypertable_cache_get_entry(Cache *cache, Oid main_table_relid)
hypertable_cache_get_entry(Cache * cache, Oid main_table_relid)
{
return hypertable_cache_get_entry_with_table(cache, main_table_relid, NULL, NULL);
}
Hypertable *
hypertable_cache_get_entry_with_table(Cache *cache, Oid main_table_relid, char *schema, char *table_name)
hypertable_cache_get_entry_with_table(Cache * cache, Oid main_table_relid, const char *schema, const char *table)
{
HypertableCacheQueryCtx ctx = {
.main_table_relid = main_table_relid,
.schema = schema,
.table_name = table_name,
.table = table,
};
HypertableNameCacheEntry *entry = cache_fetch(cache, &ctx.cctx);
if (entry->negative)
{
return NULL;
}
else
{
return &entry->entry;
}
return entry->hypertable;
}
/* function to compare epochs */
@ -227,7 +221,7 @@ cmp_epochs(const void *time_pt_pointer, const void *test)
}
PartitionEpoch *
hypertable_cache_get_partition_epoch(Cache *cache, Hypertable * hce, int64 time_pt, Oid relid)
hypertable_cache_get_partition_epoch(Cache * cache, Hypertable * hce, int64 time_pt, Oid relid)
{
MemoryContext old;
PartitionEpoch *epoch,

View File

@ -30,16 +30,15 @@ typedef struct Hypertable
extern Hypertable *hypertable_cache_get_entry(Cache * cache, Oid main_table_relid);
extern Hypertable *
hypertable_cache_get_entry_with_table(Cache *cache, Oid main_table_relid, char *schema, char *table_name);
extern Hypertable *hypertable_cache_get_entry_with_table(Cache * cache, Oid main_table_relid, const char *schema, const char *table);
PartitionEpoch *hypertable_cache_get_partition_epoch(Cache * cache, Hypertable * hce, int64 time_pt, Oid relid);
extern PartitionEpoch *hypertable_cache_get_partition_epoch(Cache * cache, Hypertable * hce, int64 time_pt, Oid relid);
void hypertable_cache_invalidate_callback(void);
extern void hypertable_cache_invalidate_callback(void);
extern Cache *hypertable_cache_pin(void);
void _hypertable_cache_init(void);
void _hypertable_cache_fini(void);
extern void _hypertable_cache_init(void);
extern void _hypertable_cache_fini(void);
#endif /* TIMESCALEDB_HYPERTABLE_CACHE_H */