summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/pgstattuple/README.pgstattuple4
-rw-r--r--contrib/pgstattuple/pgstattuple.c54
2 files changed, 38 insertions, 20 deletions
diff --git a/contrib/pgstattuple/README.pgstattuple b/contrib/pgstattuple/README.pgstattuple
index c54f97e82f5..6a191e9cced 100644
--- a/contrib/pgstattuple/README.pgstattuple
+++ b/contrib/pgstattuple/README.pgstattuple
@@ -15,7 +15,7 @@ NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 32
18.75
(1 row)
- Above example shows tellers tables includes 18.75% dead tuples.
+ Above example shows tellers table includes 18.75% dead tuples.
physical length physical size of the table in MB
live tuples information on the live tuples
@@ -40,7 +40,7 @@ NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 32
4. Notes
- pgstattuple does not lock the target table at all. So concurrent
+ pgstattuple acquires only a read lock on the table. So concurrent
update may affect the result.
pgstattuple judges a tuple is "dead" if HeapTupleSatisfiesNow()
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 45e92298100..b5afab80de1 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -1,5 +1,5 @@
/*
- * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.2 2001/10/25 05:49:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.3 2001/12/19 20:28:41 tgl Exp $
*
* Copyright (c) 2001 Tatsuo Ishii
*
@@ -23,6 +23,7 @@
*/
#include "postgres.h"
+
#include "fmgr.h"
#include "access/heapam.h"
#include "access/transam.h"
@@ -48,20 +49,21 @@ pgstattuple(PG_FUNCTION_ARGS)
HeapScanDesc scan;
HeapTuple tuple;
BlockNumber nblocks;
- BlockNumber block = InvalidBlockNumber;
+ BlockNumber block = 0; /* next block to count free space in */
+ BlockNumber tupblock;
+ Buffer buffer;
double table_len;
uint64 tuple_len = 0;
uint64 dead_tuple_len = 0;
- uint32 tuple_count = 0;
- uint32 dead_tuple_count = 0;
+ uint64 tuple_count = 0;
+ uint64 dead_tuple_count = 0;
double tuple_percent;
double dead_tuple_percent;
- Buffer buffer = InvalidBuffer;
uint64 free_space = 0; /* free/reusable space in bytes */
double free_percent; /* free/reusable space in % */
- rel = heap_openr(NameStr(*p), NoLock);
+ rel = heap_openr(NameStr(*p), AccessShareLock);
nblocks = RelationGetNumberOfBlocks(rel);
scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL);
@@ -78,17 +80,33 @@ pgstattuple(PG_FUNCTION_ARGS)
dead_tuple_count++;
}
- if (!BlockNumberIsValid(block) ||
- block != BlockIdGetBlockNumber(&tuple->t_self.ip_blkid))
+ /*
+ * To avoid physically reading the table twice, try to do the
+ * free-space scan in parallel with the heap scan. However,
+ * heap_getnext may find no tuples on a given page, so we cannot
+ * simply examine the pages returned by the heap scan.
+ */
+ tupblock = BlockIdGetBlockNumber(&tuple->t_self.ip_blkid);
+
+ while (block <= tupblock)
{
- block = BlockIdGetBlockNumber(&tuple->t_self.ip_blkid);
buffer = ReadBuffer(rel, block);
free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
ReleaseBuffer(buffer);
+ block++;
}
}
heap_endscan(scan);
- heap_close(rel, NoLock);
+
+ while (block < nblocks)
+ {
+ buffer = ReadBuffer(rel, block);
+ free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
+ ReleaseBuffer(buffer);
+ block++;
+ }
+
+ heap_close(rel, AccessShareLock);
table_len = (double) nblocks *BLCKSZ;
@@ -105,20 +123,20 @@ pgstattuple(PG_FUNCTION_ARGS)
free_percent = (double) free_space *100.0 / table_len;
}
- elog(NOTICE, "physical length: %.2fMB live tuples: %u (%.2fMB, %.2f%%) dead tuples: %u (%.2fMB, %.2f%%) free/reusable space: %.2fMB (%.2f%%) overhead: %.2f%%",
+ elog(NOTICE, "physical length: %.2fMB live tuples: %.0f (%.2fMB, %.2f%%) dead tuples: %.0f (%.2fMB, %.2f%%) free/reusable space: %.2fMB (%.2f%%) overhead: %.2f%%",
- table_len / 1024 / 1024, /* phsical length in MB */
+ table_len / (1024 * 1024), /* physical length in MB */
- tuple_count, /* number of live tuples */
- (double) tuple_len / 1024 / 1024, /* live tuples in MB */
+ (double) tuple_count, /* number of live tuples */
+ (double) tuple_len / (1024 * 1024), /* live tuples in MB */
tuple_percent, /* live tuples in % */
- dead_tuple_count, /* number of dead tuples */
- (double) dead_tuple_len / 1024 / 1024, /* dead tuples in MB */
+ (double) dead_tuple_count, /* number of dead tuples */
+ (double) dead_tuple_len / (1024 * 1024), /* dead tuples in MB */
dead_tuple_percent, /* dead tuples in % */
- (double) free_space / 1024 / 1024, /* free/available space in
- * MB */
+ (double) free_space / (1024 * 1024), /* free/available space in
+ * MB */
free_percent, /* free/available space in % */