/* * Calculate total on-disk size of a given table, * including FSM and VM, 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; * those won't have attached toast tables, but they can have multiple forks. */ static int64 calculate_table_size(Oid relOid) { int64 size = 0; Relation rel; ForkNumber forkNum; rel = relation_open(relOid, AccessShareLock); /* * heap size, including FSM and VM */ for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) size += calculate_relation_size(&(rel->rd_node), rel->rd_backend, forkNum); /* * Size of toast relation */ if (OidIsValid(rel->rd_rel->reltoastrelid)) size += calculate_toast_table_size(rel->rd_rel->reltoastrelid); relation_close(rel, AccessShareLock); return size; }
Datum pg_relation_size(PG_FUNCTION_ARGS) { Oid relOid = PG_GETARG_OID(0); text *forkName = PG_GETARG_TEXT_PP(1); Relation rel; int64 size; rel = try_relation_open(relOid, AccessShareLock); /* * Before 9.2, we used to throw an error if the relation didn't exist, but * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class" * less robust, because while we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for * already-dropped tables than throw an error and abort the whole query. */ if (rel == NULL) PG_RETURN_NULL(); size = calculate_relation_size(&(rel->rd_node), rel->rd_backend, forkname_to_number(text_to_cstring(forkName))); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
/* * Compute the on-disk size of files for the relation according to the * stat function, including heap data, index data, toast data, aoseg data, * aoblkdir data, and aovisimap data. */ static int64 calculate_total_relation_size(Oid Relid) { Relation heapRel; Oid toastOid; int64 size; ListCell *cell; ForkNumber forkNum; heapRel = try_relation_open(Relid, AccessShareLock, false); if (!RelationIsValid(heapRel)) return 0; toastOid = heapRel->rd_rel->reltoastrelid; /* Get the heap size */ if (Relid == 0 || heapRel->rd_node.relNode == 0) size = 0; else { size = 0; for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) size += calculate_relation_size(heapRel, forkNum); } /* Include any dependent indexes */ if (heapRel->rd_rel->relhasindex) { List *index_oids = RelationGetIndexList(heapRel); foreach(cell, index_oids) { Oid idxOid = lfirst_oid(cell); Relation iRel; iRel = try_relation_open(idxOid, AccessShareLock, false); if (RelationIsValid(iRel)) { for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) size += calculate_relation_size(iRel, forkNum); relation_close(iRel, AccessShareLock); } }
/* * Compute the on-disk size of files for the relation according to the * stat function, including heap data, index data, toast data, aoseg data, * aoblkdir data, and aovisimap data. */ static int64 calculate_total_relation_size(Oid Relid) { Relation heapRel; Oid toastOid; AppendOnlyEntry *aoEntry = NULL; int64 size; ListCell *cell; heapRel = try_relation_open(Relid, AccessShareLock, false); if (!RelationIsValid(heapRel)) return 0; toastOid = heapRel->rd_rel->reltoastrelid; if (RelationIsAoRows(heapRel) || RelationIsAoCols(heapRel)) aoEntry = GetAppendOnlyEntry(Relid, SnapshotNow); /* Get the heap size */ if (Relid == 0 || heapRel->rd_node.relNode == 0) size = 0; else size = calculate_relation_size(heapRel); /* Include any dependent indexes */ if (heapRel->rd_rel->relhasindex) { List *index_oids = RelationGetIndexList(heapRel); foreach(cell, index_oids) { Oid idxOid = lfirst_oid(cell); Relation iRel; iRel = try_relation_open(idxOid, AccessShareLock, false); if (RelationIsValid(iRel)) { size += calculate_relation_size(iRel); relation_close(iRel, AccessShareLock); } }
Datum pg_relation_size(PG_FUNCTION_ARGS) { Oid relOid = PG_GETARG_OID(0); text *forkName = PG_GETARG_TEXT_P(1); Relation rel; int64 size = 0; /** * This function is peculiar in that it does its own dispatching. * It does not work on entry db since we do not support dispatching * from entry-db currently. */ if (Gp_role == GP_ROLE_EXECUTE && Gp_segment == -1) elog(ERROR, "This query is not currently supported by GPDB."); rel = try_relation_open(relOid, AccessShareLock, false); /* * While we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for * already-dropped tables than throw an error and abort the whole query. */ if (!RelationIsValid(rel)) PG_RETURN_NULL(); if (relOid == 0 || rel->rd_node.relNode == 0) size = 0; else size = calculate_relation_size(rel, forkname_to_number(text_to_cstring(forkName))); if (Gp_role == GP_ROLE_DISPATCH) { StringInfoData buffer; char *schemaName; char *relName; schemaName = get_namespace_name(get_rel_namespace(relOid)); if (schemaName == NULL) elog(ERROR, "Cannot find schema for oid %d", relOid); relName = get_rel_name(relOid); if (relName == NULL) elog(ERROR, "Cannot find relation for oid %d", relOid); initStringInfo(&buffer); appendStringInfo(&buffer, "select sum(pg_relation_size('%s.%s'))::int8 from gp_dist_random('gp_id');", quote_identifier(schemaName), quote_identifier(relName)); size += get_size_from_segDBs(buffer.data); } relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
Datum pg_relation_size(PG_FUNCTION_ARGS) { Oid relOid = PG_GETARG_OID(0); text *forkName = PG_GETARG_TEXT_P(1); ForkNumber forkNumber; Relation rel; int64 size = 0; /** * This function is peculiar in that it does its own dispatching. * It does not work on entry db since we do not support dispatching * from entry-db currently. */ if (Gp_role == GP_ROLE_EXECUTE && IS_QUERY_DISPATCHER()) elog(ERROR, "This query is not currently supported by GPDB."); rel = try_relation_open(relOid, AccessShareLock, false); /* * Before 9.2, we used to throw an error if the relation didn't exist, but * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class" * less robust, because while we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for * already-dropped tables than throw an error and abort the whole query. */ if (rel == NULL) PG_RETURN_NULL(); forkNumber = forkname_to_number(text_to_cstring(forkName)); if (relOid == 0 || rel->rd_node.relNode == 0) size = 0; else size = calculate_relation_size(rel, forkNumber); if (Gp_role == GP_ROLE_DISPATCH) { char *sql; sql = psprintf("select pg_catalog.pg_relation_size(%u, '%s')", relOid, forkNames[forkNumber]); size += get_size_from_segDBs(sql); } relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
Datum pg_relation_size_oid(PG_FUNCTION_ARGS) { Oid relOid = PG_GETARG_OID(0); Relation rel; int64 size; rel = relation_open(relOid, AccessShareLock); size = calculate_relation_size(&(rel->rd_node)); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
datum_t pg_relation_size(PG_FUNC_ARGS) { oid_t relOid = ARG_OID(0); text *forkName = ARG_TEXT_P(1); struct relation * rel; int64 size; rel = relation_open(relOid, ACCESS_SHR_LOCK); size = calculate_relation_size( &(rel->rd_node), rel->rd_backend, forkname_to_number(text_to_cstring(forkName))); relation_close(rel, ACCESS_SHR_LOCK); RET_INT64(size); }
Datum pg_relation_size_name(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); RangeVar *relrv; Relation rel; int64 size; relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); size = calculate_relation_size(&(rel->rd_node)); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
Datum pg_relation_size(PG_FUNCTION_ARGS) { Oid relOid = PG_GETARG_OID(0); text *forkName = PG_GETARG_TEXT_P(1); Relation rel; int64 size; rel = relation_open(relOid, AccessShareLock); size = calculate_relation_size(&(rel->rd_node), rel->rd_backend, forkname_to_number(text_to_cstring(forkName))); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
Datum relation_size(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); RangeVar *relrv; Relation relation; Oid relnodeOid; Oid tblspcOid; relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname, "relation_size")); relation = relation_openrv(relrv, AccessShareLock); tblspcOid = relation->rd_rel->reltablespace; relnodeOid = relation->rd_rel->relfilenode; relation_close(relation, AccessShareLock); PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid)); }
/* * Calculate total on-disk size of a given table, * including FSM and VM, 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; * those won't have attached toast tables, but they can have multiple forks. */ static int64 calculate_table_size(Relation rel) { int64 size = 0; ForkNumber forkNum; /* * heap size, including FSM and VM */ for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) size += calculate_relation_size(&(rel->rd_node), rel->rd_backend, forkNum); /* * Size of toast relation */ if (OidIsValid(rel->rd_rel->reltoastrelid)) size += calculate_toast_table_size(rel->rd_rel->reltoastrelid); return size; }
/* * Calculate total on-disk size of a given table, * including FSM and VM, 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; * those won't have attached toast tables, but they can have multiple forks. */ static int64 calculate_table_size(oid_t relOid) { int64 size = 0; struct relation * rel; enum fork fnr; rel = relation_open(relOid, ACCESS_SHR_LOCK); /* * heap size, including FSM and VM */ for (fnr = 0; fnr <= MAX_FORK_NR; fnr++) size += calculate_relation_size(&(rel->rd_node), rel->rd_backend, fnr); /* * size_t of toast relation */ if (OID_VALID(rel->rd_rel->reltoastrelid)) size += calculate_toast_table_size(rel->rd_rel->reltoastrelid); relation_close(rel, ACCESS_SHR_LOCK); return size; }
Datum pg_relation_size_name(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); RangeVar *relrv; Relation rel; int64 size; if (GP_ROLE_EXECUTE == Gp_role) { ereport(ERROR, (errcode(ERRCODE_GP_COMMAND_ERROR), errmsg("pg_relation_size: cannot be executed in segment"))); } relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = try_relation_openrv(relrv, AccessShareLock, false); /* * While we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for * already-dropped tables than throw an error and abort the whole query. */ if (!RelationIsValid(rel)) PG_RETURN_NULL(); if (rel->rd_node.relNode == 0) size = 0; else size = calculate_relation_size(rel); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
Datum pg_relation_size_name(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); RangeVar *relrv; Relation rel; int64 size; /** * This function is peculiar in that it does its own dispatching. * It does not work on entry db since we do not support dispatching * from entry-db currently. */ if (Gp_role == GP_ROLE_EXECUTE && Gp_segment == -1) { elog(ERROR, "This query is not currently supported by GPDB."); } relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); if (Gp_role == GP_ROLE_EXECUTE && relrv->schemaname != NULL) { Oid namespaceId; Oid relOid; /* * Do this the hard way, because the optimizer wants to be * able to use this function on relations the user might not * have direct access to. */ AcceptInvalidationMessages(); namespaceId = caql_getoid( NULL, cql("SELECT oid FROM pg_namespace " " WHERE nspname = :1 ", CStringGetDatum(relrv->schemaname))); relOid = get_relname_relid(relrv->relname, namespaceId); if (!OidIsValid(relOid)) { size = 0; PG_RETURN_INT64(size); } /* Let relation_open do the rest */ rel = try_relation_open(relOid, AccessShareLock, false); } else rel = try_relation_openrv(relrv, AccessShareLock, false); /* * While we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for * already-dropped tables than throw an error and abort the whole query. */ if (!RelationIsValid(rel)) PG_RETURN_NULL(); if (rel->rd_node.relNode == 0) size = 0; else size = calculate_relation_size(rel); if (Gp_role == GP_ROLE_DISPATCH) { char * rawname; StringInfoData buffer; initStringInfo(&buffer); rawname = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(relname))); initStringInfo(&buffer); appendStringInfo(&buffer, "select sum(pg_relation_size('%s'))::int8 from gp_dist_random('gp_id');", rawname); size += get_size_from_segDBs(buffer.data); } relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }