mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-23 22:41:34 +08:00
Use cached Chunk struct when considering compressed paths
Full catalog lookups for a Chunk are expensive, avoiding them speeds up the planning.
This commit is contained in:
parent
fb617e4150
commit
04ce1bc498
@ -1507,7 +1507,7 @@ ts_plan_expand_hypertable_chunks(Hypertable *ht, PlannerInfo *root, RelOptInfo *
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_get_private_reloptinfo(child_rel)->chunk = chunks[i];
|
ts_get_private_reloptinfo(child_rel)->cached_chunk_struct = chunks[i];
|
||||||
Assert(chunks[i]->table_id == root->simple_rte_array[child_rtindex]->relid);
|
Assert(chunks[i]->table_id == root->simple_rte_array[child_rtindex]->relid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1096,18 +1096,17 @@ apply_optimizations(PlannerInfo *root, TsRelType reltype, RelOptInfo *rel, Range
|
|||||||
case TS_REL_CHUNK_STANDALONE:
|
case TS_REL_CHUNK_STANDALONE:
|
||||||
case TS_REL_CHUNK_CHILD:
|
case TS_REL_CHUNK_CHILD:
|
||||||
ts_sort_transform_optimization(root, rel);
|
ts_sort_transform_optimization(root, rel);
|
||||||
|
/*
|
||||||
|
* Since the sort optimization adds new paths to the rel it has
|
||||||
|
* to happen before any optimizations that replace pathlist.
|
||||||
|
*/
|
||||||
|
if (ts_cm_functions->set_rel_pathlist_query != NULL)
|
||||||
|
ts_cm_functions->set_rel_pathlist_query(root, rel, rel->relid, rte, ht);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since the sort optimization adds new paths to the rel it has
|
|
||||||
* to happen before any optimizations that replace pathlist.
|
|
||||||
*/
|
|
||||||
if (ts_cm_functions->set_rel_pathlist_query != NULL)
|
|
||||||
ts_cm_functions->set_rel_pathlist_query(root, rel, rel->relid, rte, ht);
|
|
||||||
|
|
||||||
if (reltype == TS_REL_HYPERTABLE &&
|
if (reltype == TS_REL_HYPERTABLE &&
|
||||||
#if PG14_GE
|
#if PG14_GE
|
||||||
(root->parse->commandType == CMD_SELECT || root->parse->commandType == CMD_DELETE ||
|
(root->parse->commandType == CMD_SELECT || root->parse->commandType == CMD_DELETE ||
|
||||||
|
@ -40,7 +40,7 @@ typedef struct TimescaleDBPrivate
|
|||||||
TsFdwRelInfo *fdw_relation_info;
|
TsFdwRelInfo *fdw_relation_info;
|
||||||
|
|
||||||
/* Cached chunk data for the chunk relinfo. */
|
/* Cached chunk data for the chunk relinfo. */
|
||||||
Chunk *chunk;
|
Chunk *cached_chunk_struct;
|
||||||
} TimescaleDBPrivate;
|
} TimescaleDBPrivate;
|
||||||
|
|
||||||
extern TSDLLEXPORT bool ts_rte_is_hypertable(const RangeTblEntry *rte, bool *isdistributed);
|
extern TSDLLEXPORT bool ts_rte_is_hypertable(const RangeTblEntry *rte, bool *isdistributed);
|
||||||
|
@ -78,7 +78,7 @@ data_node_chunk_assignment_assign_chunk(DataNodeChunkAssignments *scas, RelOptIn
|
|||||||
*/
|
*/
|
||||||
Oid remote_chunk_relid = InvalidOid;
|
Oid remote_chunk_relid = InvalidOid;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
foreach (lc, chunk_private->chunk->data_nodes)
|
foreach (lc, chunk_private->cached_chunk_struct->data_nodes)
|
||||||
{
|
{
|
||||||
ChunkDataNode *cdn = (ChunkDataNode *) lfirst(lc);
|
ChunkDataNode *cdn = (ChunkDataNode *) lfirst(lc);
|
||||||
if (cdn->foreign_server_oid == chunkrel->serverid)
|
if (cdn->foreign_server_oid == chunkrel->serverid)
|
||||||
@ -94,7 +94,7 @@ data_node_chunk_assignment_assign_chunk(DataNodeChunkAssignments *scas, RelOptIn
|
|||||||
*/
|
*/
|
||||||
old = MemoryContextSwitchTo(scas->mctx);
|
old = MemoryContextSwitchTo(scas->mctx);
|
||||||
sca->chunk_relids = bms_add_member(sca->chunk_relids, chunkrel->relid);
|
sca->chunk_relids = bms_add_member(sca->chunk_relids, chunkrel->relid);
|
||||||
sca->chunks = lappend(sca->chunks, chunk_private->chunk);
|
sca->chunks = lappend(sca->chunks, chunk_private->cached_chunk_struct);
|
||||||
sca->remote_chunk_ids = lappend_int(sca->remote_chunk_ids, remote_chunk_relid);
|
sca->remote_chunk_ids = lappend_int(sca->remote_chunk_ids, remote_chunk_relid);
|
||||||
sca->pages += chunkrel->pages;
|
sca->pages += chunkrel->pages;
|
||||||
sca->rows += chunkrel->rows;
|
sca->rows += chunkrel->rows;
|
||||||
|
@ -300,10 +300,10 @@ estimate_chunk_size(PlannerInfo *root, RelOptInfo *chunk_rel)
|
|||||||
* exclusion, so we'll have to look up this info now.
|
* exclusion, so we'll have to look up this info now.
|
||||||
*/
|
*/
|
||||||
TimescaleDBPrivate *chunk_private = ts_get_private_reloptinfo(chunk_rel);
|
TimescaleDBPrivate *chunk_private = ts_get_private_reloptinfo(chunk_rel);
|
||||||
if (chunk_private->chunk == NULL)
|
if (chunk_private->cached_chunk_struct == NULL)
|
||||||
{
|
{
|
||||||
RangeTblEntry *chunk_rte = planner_rt_fetch(chunk_rel->relid, root);
|
RangeTblEntry *chunk_rte = planner_rt_fetch(chunk_rel->relid, root);
|
||||||
chunk_private->chunk =
|
chunk_private->cached_chunk_struct =
|
||||||
ts_chunk_get_by_relid(chunk_rte->relid, true /* fail_if_not_found */);
|
ts_chunk_get_by_relid(chunk_rte->relid, true /* fail_if_not_found */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +319,8 @@ estimate_chunk_size(PlannerInfo *root, RelOptInfo *chunk_rel)
|
|||||||
Hypertable *ht = ts_hypertable_cache_get_entry(hcache, parent_rte->relid, CACHE_FLAG_NONE);
|
Hypertable *ht = ts_hypertable_cache_get_entry(hcache, parent_rte->relid, CACHE_FLAG_NONE);
|
||||||
Hyperspace *hyperspace = ht->space;
|
Hyperspace *hyperspace = ht->space;
|
||||||
|
|
||||||
const double fillfactor = estimate_chunk_fillfactor(chunk_private->chunk, hyperspace);
|
const double fillfactor =
|
||||||
|
estimate_chunk_fillfactor(chunk_private->cached_chunk_struct, hyperspace);
|
||||||
|
|
||||||
/* Can't have nonzero tuples in zero pages */
|
/* Can't have nonzero tuples in zero pages */
|
||||||
Assert(parent_private->average_chunk_pages != 0 || parent_private->average_chunk_tuples <= 0);
|
Assert(parent_private->average_chunk_pages != 0 || parent_private->average_chunk_tuples <= 0);
|
||||||
|
@ -121,16 +121,37 @@ tsl_set_rel_pathlist_query(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeT
|
|||||||
* We check if it is the ONLY case by calling ts_rte_is_marked_for_expansion.
|
* We check if it is the ONLY case by calling ts_rte_is_marked_for_expansion.
|
||||||
* Respecting ONLY here is important to not break postgres tools like pg_dump.
|
* Respecting ONLY here is important to not break postgres tools like pg_dump.
|
||||||
*/
|
*/
|
||||||
|
TimescaleDBPrivate *fdw_private = (TimescaleDBPrivate *) rel->fdw_private;
|
||||||
if (ts_guc_enable_transparent_decompression && ht &&
|
if (ts_guc_enable_transparent_decompression && ht &&
|
||||||
(rel->reloptkind == RELOPT_OTHER_MEMBER_REL ||
|
(rel->reloptkind == RELOPT_OTHER_MEMBER_REL ||
|
||||||
(rel->reloptkind == RELOPT_BASEREL && ts_rte_is_marked_for_expansion(rte))) &&
|
(rel->reloptkind == RELOPT_BASEREL && ts_rte_is_marked_for_expansion(rte))) &&
|
||||||
TS_HYPERTABLE_HAS_COMPRESSION_TABLE(ht) && rel->fdw_private != NULL &&
|
TS_HYPERTABLE_HAS_COMPRESSION_TABLE(ht) && fdw_private != NULL && fdw_private->compressed)
|
||||||
((TimescaleDBPrivate *) rel->fdw_private)->compressed)
|
|
||||||
{
|
{
|
||||||
Chunk *chunk = ts_chunk_get_by_relid(rte->relid, true);
|
if (fdw_private->cached_chunk_struct == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We can not have the cached Chunk struct,
|
||||||
|
* 1) if it was a direct query on the chunk;
|
||||||
|
* 2) if it is not a SELECT QUERY.
|
||||||
|
* Caching is done by our hypertable expansion, which doesn't run in
|
||||||
|
* these cases.
|
||||||
|
*
|
||||||
|
* Also on PG13 when a DELETE query runs through SPI, its command
|
||||||
|
* type is CMD_SELECT. Apparently it goes into inheritance_planner,
|
||||||
|
* which uses a hack to pretend it's actually a SELECT query, but
|
||||||
|
* for some reason for non-SPI queries the query type is still
|
||||||
|
* correct. You can observe it in the continuous_aggs-13 test.
|
||||||
|
* Just ignore this assertion on 13 and look up the chunk.
|
||||||
|
*/
|
||||||
|
#if PG14_GE
|
||||||
|
Assert(rel->reloptkind == RELOPT_BASEREL || root->parse->commandType != CMD_SELECT);
|
||||||
|
#endif
|
||||||
|
fdw_private->cached_chunk_struct =
|
||||||
|
ts_chunk_get_by_relid(rte->relid, /* fail_if_not_found = */ true);
|
||||||
|
}
|
||||||
|
|
||||||
if (chunk->fd.compressed_chunk_id != INVALID_CHUNK_ID)
|
if (fdw_private->cached_chunk_struct->fd.compressed_chunk_id != INVALID_CHUNK_ID)
|
||||||
ts_decompress_chunk_generate_paths(root, rel, ht, chunk);
|
ts_decompress_chunk_generate_paths(root, rel, ht, fdw_private->cached_chunk_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user