mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
tableam: relation creation, VACUUM FULL/CLUSTER, SET TABLESPACE.
This moves the responsibility for: - creating the storage necessary for a relation, including creating a new relfilenode for a relation with existing storage - non-transactional truncation of a relation - VACUUM FULL / CLUSTER's rewrite of a table below tableam. This is fairly straight forward, with a bit of complexity smattered in to move the computation of xid / multixid horizons below the AM, as they don't make sense for every table AM. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
This commit is contained in:
@@ -378,6 +378,46 @@ typedef struct TableAmRoutine
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* This callback needs to create a new relation filenode for `rel`, with
|
||||
* appropriate durability behaviour for `persistence`.
|
||||
*
|
||||
* On output *freezeXid, *minmulti should be set to the values appropriate
|
||||
* for pg_class.{relfrozenxid, relminmxid} have to be set to. For AMs that
|
||||
* don't need those fields to be filled they can be set to
|
||||
* InvalidTransactionId, InvalidMultiXactId respectively.
|
||||
*
|
||||
* See also table_relation_set_new_filenode().
|
||||
*/
|
||||
void (*relation_set_new_filenode) (Relation rel,
|
||||
char persistence,
|
||||
TransactionId *freezeXid,
|
||||
MultiXactId *minmulti);
|
||||
|
||||
/*
|
||||
* This callback needs to remove all contents from `rel`'s current
|
||||
* relfilenode. No provisions for transactional behaviour need to be
|
||||
* made. Often this can be implemented by truncating the underlying
|
||||
* storage to its minimal size.
|
||||
*
|
||||
* See also table_relation_nontransactional_truncate().
|
||||
*/
|
||||
void (*relation_nontransactional_truncate) (Relation rel);
|
||||
|
||||
/*
|
||||
* See table_relation_copy_data().
|
||||
*
|
||||
* This can typically be implemented by directly copying the underlying
|
||||
* storage, unless it contains references to the tablespace internally.
|
||||
*/
|
||||
void (*relation_copy_data) (Relation rel, RelFileNode newrnode);
|
||||
|
||||
/* See table_relation_copy_for_cluster() */
|
||||
void (*relation_copy_for_cluster) (Relation NewHeap, Relation OldHeap, Relation OldIndex,
|
||||
bool use_sort,
|
||||
TransactionId OldestXmin, TransactionId FreezeXid, MultiXactId MultiXactCutoff,
|
||||
double *num_tuples, double *tups_vacuumed, double *tups_recently_dead);
|
||||
|
||||
/* see table_index_build_range_scan for reference about parameters */
|
||||
double (*index_build_range_scan) (Relation heap_rel,
|
||||
Relation index_rel,
|
||||
@@ -961,6 +1001,83 @@ table_lock_tuple(Relation rel, ItemPointer tid, Snapshot snapshot,
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create a new relation filenode for `rel`, with persistence set to
|
||||
* `persistence`.
|
||||
*
|
||||
* This is used both during relation creation and various DDL operations to
|
||||
* create a new relfilenode that can be filled from scratch.
|
||||
*
|
||||
* *freezeXid, *minmulti are set to the xid / multixact horizon for the table
|
||||
* that pg_class.{relfrozenxid, relminmxid} have to be set to.
|
||||
*/
|
||||
static inline void
|
||||
table_relation_set_new_filenode(Relation rel, char persistence,
|
||||
TransactionId *freezeXid,
|
||||
MultiXactId *minmulti)
|
||||
{
|
||||
rel->rd_tableam->relation_set_new_filenode(rel, persistence,
|
||||
freezeXid, minmulti);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all table contents from `rel`, in a non-transactional manner.
|
||||
* Non-transactional meaning that there's no need to support rollbacks. This
|
||||
* commonly only is used to perform truncations for relfilenodes created in the
|
||||
* current transaction.
|
||||
*/
|
||||
static inline void
|
||||
table_relation_nontransactional_truncate(Relation rel)
|
||||
{
|
||||
rel->rd_tableam->relation_nontransactional_truncate(rel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from `rel` into the new relfilenode `newrnode`. The new
|
||||
* relfilenode may not have storage associated before this function is
|
||||
* called. This is only supposed to be used for low level operations like
|
||||
* changing a relation's tablespace.
|
||||
*/
|
||||
static inline void
|
||||
table_relation_copy_data(Relation rel, RelFileNode newrnode)
|
||||
{
|
||||
rel->rd_tableam->relation_copy_data(rel, newrnode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from `OldHeap` into `NewHeap`, as part of a CLUSTER or VACUUM
|
||||
* FULL.
|
||||
*
|
||||
* If `use_sort` is true, the table contents are sorted appropriate for
|
||||
* `OldIndex`; if use_sort is false and OldIndex is not InvalidOid, the data
|
||||
* is copied in that index's order; if use_sort is false and OidIndex is
|
||||
* InvalidOid, no sorting is performed.
|
||||
*
|
||||
* OldestXmin, FreezeXid, MultiXactCutoff need to currently valid values for
|
||||
* the table.
|
||||
*
|
||||
* *num_tuples, *tups_vacuumed, *tups_recently_dead will contain statistics
|
||||
* computed while copying for the relation. Not all might make sense for every
|
||||
* AM.
|
||||
*/
|
||||
static inline void
|
||||
table_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
|
||||
Relation OldIndex,
|
||||
bool use_sort,
|
||||
TransactionId OldestXmin,
|
||||
TransactionId FreezeXid,
|
||||
MultiXactId MultiXactCutoff,
|
||||
double *num_tuples,
|
||||
double *tups_vacuumed,
|
||||
double *tups_recently_dead)
|
||||
{
|
||||
OldHeap->rd_tableam->relation_copy_for_cluster(OldHeap, NewHeap, OldIndex,
|
||||
use_sort, OldestXmin,
|
||||
FreezeXid, MultiXactCutoff,
|
||||
num_tuples, tups_vacuumed,
|
||||
tups_recently_dead);
|
||||
}
|
||||
|
||||
/*
|
||||
* table_index_build_range_scan - scan the table to find tuples to be indexed
|
||||
*
|
||||
|
@@ -55,7 +55,9 @@ extern Relation heap_create(const char *relname,
|
||||
char relpersistence,
|
||||
bool shared_relation,
|
||||
bool mapped_relation,
|
||||
bool allow_system_table_mods);
|
||||
bool allow_system_table_mods,
|
||||
TransactionId *relfrozenxid,
|
||||
MultiXactId *relminmxid);
|
||||
|
||||
extern Oid heap_create_with_catalog(const char *relname,
|
||||
Oid relnamespace,
|
||||
@@ -79,8 +81,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);
|
||||
|
@@ -16,12 +16,15 @@
|
||||
|
||||
#include "storage/block.h"
|
||||
#include "storage/relfilenode.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/relcache.h"
|
||||
|
||||
extern void RelationCreateStorage(RelFileNode rnode, char relpersistence);
|
||||
extern void RelationDropStorage(Relation rel);
|
||||
extern void RelationPreserveStorage(RelFileNode rnode, bool atCommit);
|
||||
extern void RelationTruncate(Relation rel, BlockNumber nblocks);
|
||||
extern void RelationCopyStorage(SMgrRelation src, SMgrRelation dst,
|
||||
ForkNumber forkNum, char relpersistence);
|
||||
|
||||
/*
|
||||
* These functions used to be in storage/smgr/smgr.c, which explains the
|
||||
|
@@ -110,8 +110,7 @@ extern Relation RelationBuildLocalRelation(const char *relname,
|
||||
/*
|
||||
* Routine to manage assignment of new relfilenode to a relation
|
||||
*/
|
||||
extern void RelationSetNewRelfilenode(Relation relation, char persistence,
|
||||
TransactionId freezeXid, MultiXactId minmulti);
|
||||
extern void RelationSetNewRelfilenode(Relation relation, char persistence);
|
||||
|
||||
/*
|
||||
* Routines for flushing/rebuilding relcache entries in various scenarios
|
||||
|
Reference in New Issue
Block a user