index d1711254c4f6f6c8d0b28b046b4e8c35862a2b53..8657acc27b87d81b035bcf53189fe0f8500fa819 100644 (file)
Column | references | Description
----------------+----------------------+------------------------------------
- blockid | | Id, 1.. max_fsm_pages
- relfilenode | pg_class.relfilenode | Refilenode of the relation.
reltablespace | pg_tablespace.oid | Tablespace oid of the relation.
reldatabase | pg_database.oid | Database for the relation.
+ relfilenode | pg_class.relfilenode | Refilenode of the relation.
relblocknumber | | Offset of the page in the relation.
- blockfreebytes | | Free bytes in the block/page.
+ bytes | | Free bytes in the block/page, or NULL
+ | | for an index page (see below).
There is one row for each page in the free space map.
Because the map is shared by all the databases, there are pages from
relations not belonging to the current database.
+ The free space map can contain pages for btree indexes if they were emptied
+ by a vacuum process. The bytes field is set to NULL in this case.
+
When the pg_freespacemap view is accessed, internal free space map locks are
taken, and a copy of the map data is made for the view to display.
This ensures that the view produces a consistent set of results, while not
-------------
regression=# \d pg_freespacemap
- View "public.pg_freespacemap"
+ View "public.pg_freespacemap"
Column | Type | Modifiers
- ---------------+---------+-----------
- blockid | integer |
- relfilenode | oid |
+ ----------------+---------+-----------
reltablespace | oid |
reldatabase | oid |
+ relfilenode | oid |
relblocknumber | bigint |
- blockfreebytes | integer |
+ bytes | integer |
View definition:
- SELECT p.blockid, p.relfilenode, p.reltablespace, p.reldatabase, p.relblocknumber, p.blockfreebytes
- FROM pg_freespacemap() p(blockid integer, relfilenode oid, reltablespace oid, reldatabase oid, relblocknumber bigint, blockfreebytes integer);
+ SELECT p.reltablespace, p.reldatabase, p.relfilenode, p.relblocknumber, p.bytes
+ FROM pg_freespacemap() p(reltablespace oid, reldatabase oid, relfilenode oid, relblocknumber bigint, bytes integer);
- regression=# SELECT c.relname, m.relblocknumber, m.blockfreebytes
+ regression=# SELECT c.relname, m.relblocknumber, m.bytes
FROM pg_freespacemap m INNER JOIN pg_class c
ON c.relfilenode = m.relfilenode LIMIT 10;
- relname | relblocknumber | blockfreebytes
- ------------------------+----------------+----------------
- sql_features | 5 | 2696
- sql_implementation_info | 0 | 7104
- sql_languages | 0 | 8016
- sql_packages | 0 | 7376
- sql_sizing | 0 | 6032
- pg_authid | 0 | 7424
- pg_toast_2618 | 13 | 4588
- pg_toast_2618 | 12 | 1680
- pg_toast_2618 | 10 | 1436
- pg_toast_2618 | 7 | 1136
+ relname | relblocknumber | bytes
+ ------------------------+----------------+--------
+ sql_features | 5 | 2696
+ sql_implementation_info | 0 | 7104
+ sql_languages | 0 | 8016
+ sql_packages | 0 | 7376
+ sql_sizing | 0 | 6032
+ pg_authid | 0 | 7424
+ pg_toast_2618 | 13 | 4588
+ pg_toast_2618 | 12 | 1680
+ pg_toast_2618 | 10 | 1436
+ pg_toast_2618 | 7 | 1136
(10 rows)
regression=#
index 471c97a100be60b260629507d29e794488ab4463..7225be242c466b28cdcd121a52e5f259df51136c 100644 (file)
* pg_freespacemap.c
* display some contents of the free space map.
*
- * $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.c,v 1.2 2006年02月14日 15:03:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.c,v 1.3 2006年04月26日 22:41:18 momjian Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "storage/freespace.h"
#include "utils/relcache.h"
-#define NUM_FREESPACE_PAGES_ELEM 6
+#define NUM_FREESPACE_PAGES_ELEM 5
#if defined(WIN32) || defined(__CYGWIN__)
/* Need DLLIMPORT for some things that are not so marked in main headers */
@@ -29,12 +29,12 @@ Datum pg_freespacemap(PG_FUNCTION_ARGS);
typedef struct
{
- uint32 blockid;
- uint32 relfilenode;
uint32 reltablespace;
uint32 reldatabase;
+ uint32 relfilenode;
uint32 relblocknumber;
- uint32 blockfreebytes;
+ uint32 bytes;
+ bool isindex;
} FreeSpacePagesRec;
/* Construct a tuple to return. */
tupledesc = CreateTemplateTupleDesc(NUM_FREESPACE_PAGES_ELEM, false);
- TupleDescInitEntry(tupledesc, (AttrNumber) 1, "blockid",
- INT4OID, -1, 0);
- TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
+ TupleDescInitEntry(tupledesc, (AttrNumber) 1, "reltablespace",
OIDOID, -1, 0);
- TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
+ TupleDescInitEntry(tupledesc, (AttrNumber) 2, "reldatabase",
OIDOID, -1, 0);
- TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
+ TupleDescInitEntry(tupledesc, (AttrNumber) 3, "relfilenode",
OIDOID, -1, 0);
- TupleDescInitEntry(tupledesc, (AttrNumber) 5, "relblocknumber",
+ TupleDescInitEntry(tupledesc, (AttrNumber) 4, "relblocknumber",
INT8OID, -1, 0);
- TupleDescInitEntry(tupledesc, (AttrNumber) 6, "blockfreebytes",
+ TupleDescInitEntry(tupledesc, (AttrNumber) 5, "bytes",
INT4OID, -1, 0);
/* Generate attribute metadata needed later to produce tuples */
fctx->values[2] = (char *) palloc(3 * sizeof(uint32) + 1);
fctx->values[3] = (char *) palloc(3 * sizeof(uint32) + 1);
fctx->values[4] = (char *) palloc(3 * sizeof(uint32) + 1);
- fctx->values[5] = (char *) palloc(3 * sizeof(uint32) + 1);
/* Return to original context when allocating transient memory */
for (nPages = 0; nPages < fsmrel->storedPages; nPages++)
{
- fctx->record[i].blockid = i;
- fctx->record[i].relfilenode = fsmrel->key.relNode;
fctx->record[i].reltablespace = fsmrel->key.spcNode;
fctx->record[i].reldatabase = fsmrel->key.dbNode;
+ fctx->record[i].relfilenode = fsmrel->key.relNode;
fctx->record[i].relblocknumber = IndexFSMPageGetPageNum(page);
- fctx->record[i].blockfreebytes = 0; /* index.*/
+ fctx->record[i].bytes = 0;
+ fctx->record[i].isindex = true;
page++;
i++;
for (nPages = 0; nPages < fsmrel->storedPages; nPages++)
{
- fctx->record[i].blockid = i;
- fctx->record[i].relfilenode = fsmrel->key.relNode;
fctx->record[i].reltablespace = fsmrel->key.spcNode;
fctx->record[i].reldatabase = fsmrel->key.dbNode;
+ fctx->record[i].relfilenode = fsmrel->key.relNode;
fctx->record[i].relblocknumber = FSMPageGetPageNum(page);
- fctx->record[i].blockfreebytes = FSMPageGetSpace(page);
+ fctx->record[i].bytes = FSMPageGetSpace(page);
+ fctx->record[i].isindex = false;
page++;
i++;
if (funcctx->call_cntr < funcctx->max_calls)
{
uint32 i = funcctx->call_cntr;
+ char *values[NUM_FREESPACE_PAGES_ELEM];
+ int j;
+ /*
+ * Use a temporary values array, initially pointing to fctx->values,
+ * so it can be reassigned w/o losing the storage for subsequent
+ * calls.
+ */
+ for (j = 0; j < NUM_FREESPACE_PAGES_ELEM; j++)
+ {
+ values[j] = fctx->values[j];
+ }
+
+
+ sprintf(values[0], "%u", fctx->record[i].reltablespace);
+ sprintf(values[1], "%u", fctx->record[i].reldatabase);
+ sprintf(values[2], "%u", fctx->record[i].relfilenode);
+ sprintf(values[3], "%u", fctx->record[i].relblocknumber);
- sprintf(fctx->values[0], "%u", fctx->record[i].blockid);
- sprintf(fctx->values[1], "%u", fctx->record[i].relfilenode);
- sprintf(fctx->values[2], "%u", fctx->record[i].reltablespace);
- sprintf(fctx->values[3], "%u", fctx->record[i].reldatabase);
- sprintf(fctx->values[4], "%u", fctx->record[i].relblocknumber);
- sprintf(fctx->values[5], "%u", fctx->record[i].blockfreebytes);
+ /*
+ * Set (free) bytes to NULL for an index relation.
+ */
+ if (fctx->record[i].isindex == true)
+ {
+ values[4] = NULL;
+ }
+ else
+ {
+ sprintf(values[4], "%u", fctx->record[i].bytes);
+ }
/* Build and return the tuple. */
- tuple = BuildTupleFromCStrings(funcctx->attinmeta, fctx->values);
+ tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
result = HeapTupleGetDatum(tuple);