Use TableAm API in pg_table_size

Started by Georgiosover 5 years ago1 messages
#1Georgios
gkokolatos@protonmail.com
1 attachment(s)

Hi,

I noticed that there are several file layout assumptions in dbsize.c which might not hold true for non heap relations attached with the TableAm API. It seems logical that in order to retrieve the disk size of a relation, the existing size method to be used instead.

A small patch is included to demonstrate how such an implementation can look like. Also, the existing method for heap, table_block_relation_size, should be able to address the valid cases where a fork number does not exist.

If this is considered valid, then the same can be applied for indexes too. The more generic calculate_relation_size can be adapted to call into the TableAm for those kinds of relations that makes sense. If agreed, a more complete patch can be provided.

Cheers,
//Georgios

Attachments:

0001-Use-tableam-for-pg_table_size.patchapplication/octet-stream; name=0001-Use-tableam-for-pg_table_size.patchDownload
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index c814733b22..9cce6c3f34 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -516,10 +516,14 @@ table_block_relation_size(Relation rel, ForkNumber forkNumber)
 	if (forkNumber == InvalidForkNumber)
 	{
 		for (int i = 0; i < MAX_FORKNUM; i++)
-			nblocks += smgrnblocks(rel->rd_smgr, i);
+			nblocks += smgrexists(rel->rd_smgr, i)
+						? smgrnblocks(rel->rd_smgr, i)
+						: 0;
 	}
 	else
-		nblocks = smgrnblocks(rel->rd_smgr, forkNumber);
+		nblocks += smgrexists(rel->rd_smgr, forkNumber)
+					? smgrnblocks(rel->rd_smgr, forkNumber)
+					: 0;
 
 	return nblocks * BLCKSZ;
 }
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 840664429e..ce51726bc7 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -15,6 +15,7 @@
 
 #include "access/htup_details.h"
 #include "access/relation.h"
+#include "access/tableam.h"
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_authid.h"
@@ -342,7 +343,7 @@ pg_relation_size(PG_FUNCTION_ARGS)
 static int64
 calculate_toast_table_size(Oid toastrelid)
 {
-	int64		size = 0;
+	uint64		size = 0;
 	Relation	toastRel;
 	ForkNumber	forkNum;
 	ListCell   *lc;
@@ -352,8 +353,7 @@ calculate_toast_table_size(Oid toastrelid)
 
 	/* toast heap size, including FSM and VM size */
 	for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
-		size += calculate_relation_size(&(toastRel->rd_node),
-										toastRel->rd_backend, forkNum);
+		size += table_relation_size(toastRel, forkNum);
 
 	/* toast index size, including FSM and VM size */
 	indexlist = RelationGetIndexList(toastRel);
@@ -374,29 +374,30 @@ calculate_toast_table_size(Oid toastrelid)
 	list_free(indexlist);
 	relation_close(toastRel, AccessShareLock);
 
-	return size;
+	Assert(size < PG_INT64_MAX);
+
+	return (int64)size;
 }
 
 /*
  * Calculate total on-disk size of a given table,
- * including FSM and VM, plus TOAST table if any.
+ * plus TOAST table if any.
  * Indexes other than the TOAST table's index are not included.
  *
- * Note that this also behaves sanely if applied to an index or toast table;
+ * Note that this also behaves sanely if applied to a toast table;
  * those won't have attached toast tables, but they can have multiple forks.
  */
 static int64
 calculate_table_size(Relation rel)
 {
-	int64		size = 0;
+	uint64		size = 0;
 	ForkNumber	forkNum;
 
 	/*
-	 * heap size, including FSM and VM
+	 * table size, including FSM and VM
 	 */
 	for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
-		size += calculate_relation_size(&(rel->rd_node), rel->rd_backend,
-										forkNum);
+		size += table_relation_size(rel, forkNum);
 
 	/*
 	 * Size of toast relation
@@ -404,7 +405,9 @@ calculate_table_size(Relation rel)
 	if (OidIsValid(rel->rd_rel->reltoastrelid))
 		size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
 
-	return size;
+	Assert(size < PG_INT64_MAX);
+
+	return (int64)size;
 }
 
 /*
@@ -452,14 +455,17 @@ pg_table_size(PG_FUNCTION_ARGS)
 {
 	Oid			relOid = PG_GETARG_OID(0);
 	Relation	rel;
-	int64		size;
+	int64		size = 0;
 
 	rel = try_relation_open(relOid, AccessShareLock);
 
 	if (rel == NULL)
 		PG_RETURN_NULL();
 
-	size = calculate_table_size(rel);
+	if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind)	&&
+		rel->rd_rel->relkind != RELKIND_INDEX		&&
+		rel->rd_rel->relkind != RELKIND_SEQUENCE)
+		size = calculate_table_size(rel);
 
 	relation_close(rel, AccessShareLock);
 
@@ -487,7 +493,7 @@ pg_indexes_size(PG_FUNCTION_ARGS)
 
 /*
  *	Compute the on-disk size of all files for the relation,
- *	including heap data, index data, toast data, FSM, VM.
+ *	including table data, index data, toast data.
  */
 static int64
 calculate_total_relation_size(Relation rel)