From cab9a0656c36739f59277b34fea8ab9438395869 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 23 Aug 2009 19:23:41 +0000 Subject: Make TRUNCATE do truncate-in-place when processing a relation that was created or previously truncated in the current (sub)transaction. This is safe since if the (sub)transaction later rolls back, we'd just discard the rel's current physical file anyway. This avoids unreasonable growth in the number of transient files when a relation is repeatedly truncated. Per a performance gripe a couple weeks ago from Todd Cook. --- src/backend/commands/tablecmds.c | 67 +++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 22 deletions(-) (limited to 'src/backend/commands/tablecmds.c') diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 07bc3932003..a36cbc51aff 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.297 2009/08/12 23:00:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.298 2009/08/23 19:23:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -775,6 +775,7 @@ ExecuteTruncate(TruncateStmt *stmt) EState *estate; ResultRelInfo *resultRelInfos; ResultRelInfo *resultRelInfo; + SubTransactionId mySubid; ListCell *cell; /* @@ -944,36 +945,58 @@ ExecuteTruncate(TruncateStmt *stmt) /* * OK, truncate each table. */ + mySubid = GetCurrentSubTransactionId(); + foreach(cell, rels) { Relation rel = (Relation) lfirst(cell); - Oid heap_relid; - Oid toast_relid; /* - * Create a new empty storage file for the relation, and assign it as - * the relfilenode value. The old storage file is scheduled for - * deletion at commit. + * Normally, we need a transaction-safe truncation here. However, + * if the table was either created in the current (sub)transaction + * or has a new relfilenode in the current (sub)transaction, then + * we can just truncate it in-place, because a rollback would + * cause the whole table or the current physical file to be + * thrown away anyway. */ - setNewRelfilenode(rel, RecentXmin); - - heap_relid = RelationGetRelid(rel); - toast_relid = rel->rd_rel->reltoastrelid; - - /* - * The same for the toast table, if any. - */ - if (OidIsValid(toast_relid)) + if (rel->rd_createSubid == mySubid || + rel->rd_newRelfilenodeSubid == mySubid) { - rel = relation_open(toast_relid, AccessExclusiveLock); - setNewRelfilenode(rel, RecentXmin); - heap_close(rel, NoLock); + /* Immediate, non-rollbackable truncation is OK */ + heap_truncate_one_rel(rel); } + else + { + Oid heap_relid; + Oid toast_relid; - /* - * Reconstruct the indexes to match, and we're done. - */ - reindex_relation(heap_relid, true); + /* + * Need the full transaction-safe pushups. + * + * Create a new empty storage file for the relation, and assign it + * as the relfilenode value. The old storage file is scheduled for + * deletion at commit. + */ + setNewRelfilenode(rel, RecentXmin); + + heap_relid = RelationGetRelid(rel); + toast_relid = rel->rd_rel->reltoastrelid; + + /* + * The same for the toast table, if any. + */ + if (OidIsValid(toast_relid)) + { + rel = relation_open(toast_relid, AccessExclusiveLock); + setNewRelfilenode(rel, RecentXmin); + heap_close(rel, NoLock); + } + + /* + * Reconstruct the indexes to match, and we're done. + */ + reindex_relation(heap_relid, true); + } } /* -- cgit v1.2.3