From: Andres Freund Date: Thu, 6 Dec 2018 04:09:05 +0000 (-0800) Subject: WIP: pluggable init fork creation, relation size estimation, file creation. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=1bbee18e32b958ed2d42e47d528f6b4daefd90f3;p=users%2Fandresfreund%2Fpostgres.git WIP: pluggable init fork creation, relation size estimation, file creation. This doesn't yet really work. --- diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 49f8d833f6..95513dfec8 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -30,6 +30,7 @@ #include "catalog/catalog.h" #include "catalog/index.h" #include "catalog/pg_am_d.h" +#include "catalog/storage_xlog.h" #include "executor/executor.h" #include "pgstat.h" #include "storage/lmgr.h" @@ -2062,6 +2063,28 @@ heap_copy_for_cluster(Relation OldHeap, Relation NewHeap, Relation OldIndex, pfree(isnull); } +/* + * Set up an init fork for an unlogged table so that it can be correctly + * reinitialized on restart. An immediate sync is required even if the + * page has been logged, because the write did not go through + * shared_buffers and therefore a concurrent checkpoint may have moved + * the redo pointer past our xlog record. Recovery may as well remove it + * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE + * record. Therefore, logging is necessary even if wal_level=minimal. + */ +static void +heap_create_init_fork(Relation rel) +{ + Assert(rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_MATVIEW || + rel->rd_rel->relkind == RELKIND_TOASTVALUE); + RelationOpenSmgr(rel); + smgrcreate(rel->rd_smgr, INIT_FORKNUM, false); + log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM); + smgrimmedsync(rel->rd_smgr, INIT_FORKNUM); +} + + static const TableAmRoutine heapam_methods = { .type = T_TableAmRoutine, @@ -2098,6 +2121,7 @@ static const TableAmRoutine heapam_methods = { .scan_analyze_next_block = heapam_scan_analyze_next_block, .scan_analyze_next_tuple = heapam_scan_analyze_next_tuple, .relation_copy_for_cluster = heap_copy_for_cluster, + .relation_create_init_fork = heap_create_init_fork, .relation_sync = heap_sync, .begin_index_fetch = heapam_begin_index_fetch, diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index f85eab1714..a3015333f3 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -32,6 +32,7 @@ #include "access/htup_details.h" #include "access/multixact.h" #include "access/sysattr.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" #include "access/xlog.h" @@ -1396,7 +1397,7 @@ heap_create_with_catalog(const char *relname, */ if (relpersistence == RELPERSISTENCE_UNLOGGED && relkind != RELKIND_PARTITIONED_TABLE) - heap_create_init_fork(new_rel_desc); + table_create_init_fork(new_rel_desc); /* * ok, the relation has been cataloged, so close our relations and return @@ -1408,27 +1409,6 @@ heap_create_with_catalog(const char *relname, return relid; } -/* - * Set up an init fork for an unlogged table so that it can be correctly - * reinitialized on restart. An immediate sync is required even if the - * page has been logged, because the write did not go through - * shared_buffers and therefore a concurrent checkpoint may have moved - * the redo pointer past our xlog record. Recovery may as well remove it - * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE - * record. Therefore, logging is necessary even if wal_level=minimal. - */ -void -heap_create_init_fork(Relation rel) -{ - Assert(rel->rd_rel->relkind == RELKIND_RELATION || - rel->rd_rel->relkind == RELKIND_MATVIEW || - rel->rd_rel->relkind == RELKIND_TOASTVALUE); - RelationOpenSmgr(rel); - smgrcreate(rel->rd_smgr, INIT_FORKNUM, false); - log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM); - smgrimmedsync(rel->rd_smgr, INIT_FORKNUM); -} - /* * RelationRemoveInheritance * diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 20f1e5f2c6..959b824e88 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1624,7 +1624,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence, RecentXmin, minmulti); if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED) - heap_create_init_fork(rel); + table_create_init_fork(rel); heap_relid = RelationGetRelid(rel); @@ -1641,7 +1641,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, toastrel->rd_rel->relpersistence, RecentXmin, minmulti); if (toastrel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED) - heap_create_init_fork(toastrel); + table_create_init_fork(toastrel); heap_close(toastrel, NoLock); } diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 58e8c7cc5f..5e1b27be75 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -946,6 +946,20 @@ estimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber relallvisible; double density; +#if 0 + /* + * If the relation contains any specific EstimateRelSize + * function, use that instead of the regular default heap method. + */ + if (rel->rd_tableamroutine && + rel->rd_tableamroutine->EstimateRelSize) + { + rel->rd_tableamroutine->EstimateRelSize(rel, attr_widths, pages, + tuples, allvisfrac); + return; + } +#endif + switch (rel->rd_rel->relkind) { case RELKIND_RELATION: diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 8b79e59077..120550f526 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -3417,6 +3417,21 @@ RelationSetNewRelfilenode(Relation relation, char persistence, HeapTuple tuple; Form_pg_class classform; + +#if 0 + /* + * If the relation contains any specific SetNewFilenode + * function, use that instead of the regular default heap method. + */ + if (relation->rd_tableamroutine && + relation->rd_tableamroutine->SetNewFileNode) + { + relation->rd_tableamroutine->SetNewFileNode(relation, persistence, + freezeXid, minmulti); + return; + } +#endif + /* Indexes, sequences must have Invalid frozenxid; other rels must not */ Assert((relation->rd_rel->relkind == RELKIND_INDEX || relation->rd_rel->relkind == RELKIND_SEQUENCE) ? diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index 7364afa340..966c0e00d8 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -114,7 +114,13 @@ typedef void (*RelationCopyForCluster_function)(Relation NewHeap, Relation OldHe TransactionId OldestXmin, TransactionId FreezeXid, MultiXactId MultiXactCutoff, double *num_tuples, double *tups_vacuumed, double *tups_recently_dead); +typedef void (*RelationCreateInitFork_function)(Relation rel); +typedef void (*RelationSetNewFileNode_function)(Relation relation, char persistence, + TransactionId freezeXid, MultiXactId minmulti); typedef void (*RelationSync_function) (Relation relation); +typedef void (*RelationEstimateSize_function)(Relation rel, int32 *attr_widths, + BlockNumber *pages, double *tuples, double *allvisfrac); + typedef const TupleTableSlotOps* (*SlotCallbacks_function) (Relation relation); @@ -206,7 +212,11 @@ typedef struct TableAmRoutine RelationScanAnalyzeNextBlock_function scan_analyze_next_block; RelationScanAnalyzeNextTuple_function scan_analyze_next_tuple; RelationCopyForCluster_function relation_copy_for_cluster; + + RelationCreateInitFork_function relation_create_init_fork; + RelationSetNewFileNode_function relation_set_new_filenode; RelationSync_function relation_sync; + RelationEstimateSize_function relation_estimate_size; /* Operations on relation scans */ ScanBegin_function scan_begin; @@ -646,6 +656,20 @@ table_copy_for_cluster(Relation OldHeap, Relation NewHeap, Relation OldIndex, num_tuples, tups_vacuumed, tups_recently_dead); } +static inline void +table_create_init_fork(Relation rel) +{ + rel->rd_tableamroutine->relation_create_init_fork(rel); +} + +static inline void +table_set_new_filenode(Relation rel, char persistence, + TransactionId freezeXid, MultiXactId minmulti) +{ + rel->rd_tableamroutine->relation_set_new_filenode(rel, persistence, + freezeXid, minmulti); +} + /* * table_sync - sync a heap, for use when no WAL has been written */ @@ -655,6 +679,14 @@ table_sync(Relation rel) rel->rd_tableamroutine->relation_sync(rel); } +static inline void +table_estimate_size(Relation rel, int32 *attr_widths, + BlockNumber *pages, double *tuples, double *allvisfrac) +{ + rel->rd_tableamroutine->relation_estimate_size(rel, attr_widths, + pages, tuples, allvisfrac); +} + static inline double table_index_build_scan(Relation heapRelation, Relation indexRelation, diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index cedc19fbcf..9fbca37269 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -75,8 +75,6 @@ extern Oid heap_create_with_catalog(const char *relname, Oid relrewrite, ObjectAddress *typaddress); -extern void heap_create_init_fork(Relation rel); - extern void heap_drop_with_catalog(Oid relid); extern void heap_truncate(List *relids);