Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cab9a06

Browse files
committed
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.
1 parent c38b759 commit cab9a06

File tree

3 files changed

+85
-41
lines changed

3 files changed

+85
-41
lines changed

src/backend/catalog/heap.c

+37-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.357 2009/08/02 22:14:52 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.358 2009/08/23 19:23:40 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -2342,18 +2342,9 @@ heap_truncate(List *relids)
23422342
{
23432343
Oid rid = lfirst_oid(cell);
23442344
Relation rel;
2345-
Oid toastrelid;
23462345

23472346
rel = heap_open(rid, AccessExclusiveLock);
23482347
relations = lappend(relations, rel);
2349-
2350-
/* If there is a toast table, add it to the list too */
2351-
toastrelid = rel->rd_rel->reltoastrelid;
2352-
if (OidIsValid(toastrelid))
2353-
{
2354-
rel = heap_open(toastrelid, AccessExclusiveLock);
2355-
relations = lappend(relations, rel);
2356-
}
23572348
}
23582349

23592350
/* Don't allow truncate on tables that are referenced by foreign keys */
@@ -2364,19 +2355,47 @@ heap_truncate(List *relids)
23642355
{
23652356
Relation rel = lfirst(cell);
23662357

2367-
/* Truncate the actual file (and discard buffers) */
2368-
RelationTruncate(rel, 0);
2358+
/* Truncate the relation */
2359+
heap_truncate_one_rel(rel);
23692360

2370-
/* If this relation has indexes, truncate the indexes too */
2371-
RelationTruncateIndexes(rel);
2372-
2373-
/*
2374-
* Close the relation, but keep exclusive lock on it until commit.
2375-
*/
2361+
/* Close the relation, but keep exclusive lock on it until commit */
23762362
heap_close(rel, NoLock);
23772363
}
23782364
}
23792365

2366+
/*
2367+
* heap_truncate_one_rel
2368+
*
2369+
* This routine deletes all data within the specified relation.
2370+
*
2371+
* This is not transaction-safe, because the truncation is done immediately
2372+
* and cannot be rolled back later. Caller is responsible for having
2373+
* checked permissions etc, and must have obtained AccessExclusiveLock.
2374+
*/
2375+
void
2376+
heap_truncate_one_rel(Relation rel)
2377+
{
2378+
Oid toastrelid;
2379+
2380+
/* Truncate the actual file (and discard buffers) */
2381+
RelationTruncate(rel, 0);
2382+
2383+
/* If the relation has indexes, truncate the indexes too */
2384+
RelationTruncateIndexes(rel);
2385+
2386+
/* If there is a toast table, truncate that too */
2387+
toastrelid = rel->rd_rel->reltoastrelid;
2388+
if (OidIsValid(toastrelid))
2389+
{
2390+
Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
2391+
2392+
RelationTruncate(toastrel, 0);
2393+
RelationTruncateIndexes(toastrel);
2394+
/* keep the lock... */
2395+
heap_close(toastrel, NoLock);
2396+
}
2397+
}
2398+
23802399
/*
23812400
* heap_truncate_check_FKs
23822401
* Check for foreign keys referencing a list of relations that

src/backend/commands/tablecmds.c

+45-22
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.297 2009/08/12 23:00:12 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.298 2009/08/23 19:23:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -775,6 +775,7 @@ ExecuteTruncate(TruncateStmt *stmt)
775775
EState *estate;
776776
ResultRelInfo *resultRelInfos;
777777
ResultRelInfo *resultRelInfo;
778+
SubTransactionId mySubid;
778779
ListCell *cell;
779780

780781
/*
@@ -944,36 +945,58 @@ ExecuteTruncate(TruncateStmt *stmt)
944945
/*
945946
* OK, truncate each table.
946947
*/
948+
mySubid = GetCurrentSubTransactionId();
949+
947950
foreach(cell, rels)
948951
{
949952
Relation rel = (Relation) lfirst(cell);
950-
Oid heap_relid;
951-
Oid toast_relid;
952953

953954
/*
954-
* Create a new empty storage file for the relation, and assign it as
955-
* the relfilenode value. The old storage file is scheduled for
956-
* deletion at commit.
955+
* Normally, we need a transaction-safe truncation here. However,
956+
* if the table was either created in the current (sub)transaction
957+
* or has a new relfilenode in the current (sub)transaction, then
958+
* we can just truncate it in-place, because a rollback would
959+
* cause the whole table or the current physical file to be
960+
* thrown away anyway.
957961
*/
958-
setNewRelfilenode(rel, RecentXmin);
959-
960-
heap_relid = RelationGetRelid(rel);
961-
toast_relid = rel->rd_rel->reltoastrelid;
962-
963-
/*
964-
* The same for the toast table, if any.
965-
*/
966-
if (OidIsValid(toast_relid))
962+
if (rel->rd_createSubid == mySubid ||
963+
rel->rd_newRelfilenodeSubid == mySubid)
967964
{
968-
rel = relation_open(toast_relid, AccessExclusiveLock);
969-
setNewRelfilenode(rel, RecentXmin);
970-
heap_close(rel, NoLock);
965+
/* Immediate, non-rollbackable truncation is OK */
966+
heap_truncate_one_rel(rel);
971967
}
968+
else
969+
{
970+
Oid heap_relid;
971+
Oid toast_relid;
972972

973-
/*
974-
* Reconstruct the indexes to match, and we're done.
975-
*/
976-
reindex_relation(heap_relid, true);
973+
/*
974+
* Need the full transaction-safe pushups.
975+
*
976+
* Create a new empty storage file for the relation, and assign it
977+
* as the relfilenode value. The old storage file is scheduled for
978+
* deletion at commit.
979+
*/
980+
setNewRelfilenode(rel, RecentXmin);
981+
982+
heap_relid = RelationGetRelid(rel);
983+
toast_relid = rel->rd_rel->reltoastrelid;
984+
985+
/*
986+
* The same for the toast table, if any.
987+
*/
988+
if (OidIsValid(toast_relid))
989+
{
990+
rel = relation_open(toast_relid, AccessExclusiveLock);
991+
setNewRelfilenode(rel, RecentXmin);
992+
heap_close(rel, NoLock);
993+
}
994+
995+
/*
996+
* Reconstruct the indexes to match, and we're done.
997+
*/
998+
reindex_relation(heap_relid, true);
999+
}
9771000
}
9781001

9791002
/*

src/include/catalog/heap.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.91 2009/06/11 14:49:09 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.92 2009/08/23 19:23:41 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -62,6 +62,8 @@ extern void heap_drop_with_catalog(Oid relid);
6262

6363
extern void heap_truncate(List *relids);
6464

65+
extern void heap_truncate_one_rel(Relation rel);
66+
6567
extern void heap_truncate_check_FKs(List *relations, bool tempTables);
6668

6769
extern List *heap_truncate_find_FKs(List *relationIds);

0 commit comments

Comments
 (0)