Commit d287818e authored by Tom Lane's avatar Tom Lane

Adjust pgstatindex() to give correct answers for indexes larger than

2^31 blocks.  Also fix pg_relpages() for the same case.
Tatsuhito Kasahara
parent 458c5856
...@@ -59,19 +59,19 @@ PG_FUNCTION_INFO_V1(pg_relpages); ...@@ -59,19 +59,19 @@ PG_FUNCTION_INFO_V1(pg_relpages);
typedef struct BTIndexStat typedef struct BTIndexStat
{ {
uint32 version; uint32 version;
BlockNumber root_blkno;
uint32 level; uint32 level;
BlockNumber root_blkno;
uint32 root_pages; uint64 root_pages;
uint32 internal_pages; uint64 internal_pages;
uint32 leaf_pages; uint64 leaf_pages;
uint32 empty_pages; uint64 empty_pages;
uint32 deleted_pages; uint64 deleted_pages;
uint32 max_avail; uint64 max_avail;
uint32 free_space; uint64 free_space;
uint32 fragments; uint64 fragments;
} BTIndexStat; } BTIndexStat;
/* ------------------------------------------------------ /* ------------------------------------------------------
...@@ -87,8 +87,8 @@ pgstatindex(PG_FUNCTION_ARGS) ...@@ -87,8 +87,8 @@ pgstatindex(PG_FUNCTION_ARGS)
Relation rel; Relation rel;
RangeVar *relrv; RangeVar *relrv;
Datum result; Datum result;
uint32 nblocks; BlockNumber nblocks;
uint32 blkno; BlockNumber blkno;
BTIndexStat indexStat; BTIndexStat indexStat;
if (!superuser()) if (!superuser())
...@@ -112,30 +112,29 @@ pgstatindex(PG_FUNCTION_ARGS) ...@@ -112,30 +112,29 @@ pgstatindex(PG_FUNCTION_ARGS)
BTMetaPageData *metad = BTPageGetMeta(page); BTMetaPageData *metad = BTPageGetMeta(page);
indexStat.version = metad->btm_version; indexStat.version = metad->btm_version;
indexStat.root_blkno = metad->btm_root;
indexStat.level = metad->btm_level; indexStat.level = metad->btm_level;
indexStat.root_blkno = metad->btm_root;
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
} }
nblocks = RelationGetNumberOfBlocks(rel); /* -- init counters -- */
/* -- init stat -- */
indexStat.fragments = 0;
indexStat.root_pages = 0; indexStat.root_pages = 0;
indexStat.leaf_pages = 0;
indexStat.internal_pages = 0; indexStat.internal_pages = 0;
indexStat.leaf_pages = 0;
indexStat.empty_pages = 0; indexStat.empty_pages = 0;
indexStat.deleted_pages = 0; indexStat.deleted_pages = 0;
indexStat.max_avail = 0; indexStat.max_avail = 0;
indexStat.free_space = 0; indexStat.free_space = 0;
/*----------------------- indexStat.fragments = 0;
* Scan all blocks
*----------------------- /*
* Scan all blocks except the metapage
*/ */
nblocks = RelationGetNumberOfBlocks(rel);
for (blkno = 1; blkno < nblocks; blkno++) for (blkno = 1; blkno < nblocks; blkno++)
{ {
Buffer buffer; Buffer buffer;
...@@ -151,13 +150,7 @@ pgstatindex(PG_FUNCTION_ARGS) ...@@ -151,13 +150,7 @@ pgstatindex(PG_FUNCTION_ARGS)
/* Determine page type, and update totals */ /* Determine page type, and update totals */
if (P_ISDELETED(opaque)) if (P_ISLEAF(opaque))
indexStat.deleted_pages++;
else if (P_IGNORE(opaque))
indexStat.empty_pages++;
else if (P_ISLEAF(opaque))
{ {
int max_avail; int max_avail;
...@@ -174,9 +167,12 @@ pgstatindex(PG_FUNCTION_ARGS) ...@@ -174,9 +167,12 @@ pgstatindex(PG_FUNCTION_ARGS)
if (opaque->btpo_next != P_NONE && opaque->btpo_next < blkno) if (opaque->btpo_next != P_NONE && opaque->btpo_next < blkno)
indexStat.fragments++; indexStat.fragments++;
} }
else if (P_ISDELETED(opaque))
indexStat.deleted_pages++;
else if (P_IGNORE(opaque))
indexStat.empty_pages++;
else if (P_ISROOT(opaque)) else if (P_ISROOT(opaque))
indexStat.root_pages++; indexStat.root_pages++;
else else
indexStat.internal_pages++; indexStat.internal_pages++;
...@@ -207,25 +203,26 @@ pgstatindex(PG_FUNCTION_ARGS) ...@@ -207,25 +203,26 @@ pgstatindex(PG_FUNCTION_ARGS)
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", indexStat.level); snprintf(values[j++], 32, "%d", indexStat.level);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", (indexStat.root_pages + snprintf(values[j++], 32, INT64_FORMAT,
indexStat.leaf_pages + (indexStat.root_pages +
indexStat.internal_pages + indexStat.leaf_pages +
indexStat.deleted_pages + indexStat.internal_pages +
indexStat.empty_pages) * BLCKSZ); indexStat.deleted_pages +
indexStat.empty_pages) * BLCKSZ);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", indexStat.root_blkno); snprintf(values[j++], 32, "%u", indexStat.root_blkno);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", indexStat.internal_pages); snprintf(values[j++], 32, INT64_FORMAT, indexStat.internal_pages);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", indexStat.leaf_pages); snprintf(values[j++], 32, INT64_FORMAT, indexStat.leaf_pages);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", indexStat.empty_pages); snprintf(values[j++], 32, INT64_FORMAT, indexStat.empty_pages);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%d", indexStat.deleted_pages); snprintf(values[j++], 32, INT64_FORMAT, indexStat.deleted_pages);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%.2f", 100.0 - (float) indexStat.free_space / (float) indexStat.max_avail * 100.0); snprintf(values[j++], 32, "%.2f", 100.0 - (double) indexStat.free_space / (double) indexStat.max_avail * 100.0);
values[j] = palloc(32); values[j] = palloc(32);
snprintf(values[j++], 32, "%.2f", (float) indexStat.fragments / (float) indexStat.leaf_pages * 100.0); snprintf(values[j++], 32, "%.2f", (double) indexStat.fragments / (double) indexStat.leaf_pages * 100.0);
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
values); values);
...@@ -249,9 +246,9 @@ Datum ...@@ -249,9 +246,9 @@ Datum
pg_relpages(PG_FUNCTION_ARGS) pg_relpages(PG_FUNCTION_ARGS)
{ {
text *relname = PG_GETARG_TEXT_P(0); text *relname = PG_GETARG_TEXT_P(0);
int64 relpages;
Relation rel; Relation rel;
RangeVar *relrv; RangeVar *relrv;
int4 relpages;
if (!superuser()) if (!superuser())
ereport(ERROR, ereport(ERROR,
...@@ -265,5 +262,5 @@ pg_relpages(PG_FUNCTION_ARGS) ...@@ -265,5 +262,5 @@ pg_relpages(PG_FUNCTION_ARGS)
relation_close(rel, AccessShareLock); relation_close(rel, AccessShareLock);
PG_RETURN_INT32(relpages); PG_RETURN_INT64(relpages);
} }
/* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.sql.in,v 1.15 2007/11/13 04:24:28 momjian Exp $ */ /* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.sql.in,v 1.16 2008/03/21 03:23:30 tgl Exp $ */
-- Adjust this setting to control where the objects get created. -- Adjust this setting to control where the objects get created.
SET search_path = public; SET search_path = public;
...@@ -7,12 +7,12 @@ CREATE OR REPLACE FUNCTION pgstattuple(IN relname text, ...@@ -7,12 +7,12 @@ CREATE OR REPLACE FUNCTION pgstattuple(IN relname text,
OUT table_len BIGINT, -- physical table length in bytes OUT table_len BIGINT, -- physical table length in bytes
OUT tuple_count BIGINT, -- number of live tuples OUT tuple_count BIGINT, -- number of live tuples
OUT tuple_len BIGINT, -- total tuples length in bytes OUT tuple_len BIGINT, -- total tuples length in bytes
OUT tuple_percent FLOAT, -- live tuples in % OUT tuple_percent FLOAT8, -- live tuples in %
OUT dead_tuple_count BIGINT, -- number of dead tuples OUT dead_tuple_count BIGINT, -- number of dead tuples
OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes
OUT dead_tuple_percent FLOAT, -- dead tuples in % OUT dead_tuple_percent FLOAT8, -- dead tuples in %
OUT free_space BIGINT, -- free space in bytes OUT free_space BIGINT, -- free space in bytes
OUT free_percent FLOAT) -- free space in % OUT free_percent FLOAT8) -- free space in %
AS 'MODULE_PATHNAME', 'pgstattuple' AS 'MODULE_PATHNAME', 'pgstattuple'
LANGUAGE C STRICT; LANGUAGE C STRICT;
...@@ -20,36 +20,30 @@ CREATE OR REPLACE FUNCTION pgstattuple(IN reloid oid, ...@@ -20,36 +20,30 @@ CREATE OR REPLACE FUNCTION pgstattuple(IN reloid oid,
OUT table_len BIGINT, -- physical table length in bytes OUT table_len BIGINT, -- physical table length in bytes
OUT tuple_count BIGINT, -- number of live tuples OUT tuple_count BIGINT, -- number of live tuples
OUT tuple_len BIGINT, -- total tuples length in bytes OUT tuple_len BIGINT, -- total tuples length in bytes
OUT tuple_percent FLOAT, -- live tuples in % OUT tuple_percent FLOAT8, -- live tuples in %
OUT dead_tuple_count BIGINT, -- number of dead tuples OUT dead_tuple_count BIGINT, -- number of dead tuples
OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes
OUT dead_tuple_percent FLOAT, -- dead tuples in % OUT dead_tuple_percent FLOAT8, -- dead tuples in %
OUT free_space BIGINT, -- free space in bytes OUT free_space BIGINT, -- free space in bytes
OUT free_percent FLOAT) -- free space in % OUT free_percent FLOAT8) -- free space in %
AS 'MODULE_PATHNAME', 'pgstattuplebyid' AS 'MODULE_PATHNAME', 'pgstattuplebyid'
LANGUAGE C STRICT; LANGUAGE C STRICT;
--
-- pgstatindex
--
CREATE OR REPLACE FUNCTION pgstatindex(IN relname text, CREATE OR REPLACE FUNCTION pgstatindex(IN relname text,
OUT version int4, OUT version INT,
OUT tree_level int4, OUT tree_level INT,
OUT index_size int4, OUT index_size BIGINT,
OUT root_block_no int4, OUT root_block_no BIGINT,
OUT internal_pages int4, OUT internal_pages BIGINT,
OUT leaf_pages int4, OUT leaf_pages BIGINT,
OUT empty_pages int4, OUT empty_pages BIGINT,
OUT deleted_pages int4, OUT deleted_pages BIGINT,
OUT avg_leaf_density float8, OUT avg_leaf_density FLOAT8,
OUT leaf_fragmentation float8) OUT leaf_fragmentation FLOAT8)
AS 'MODULE_PATHNAME', 'pgstatindex' AS 'MODULE_PATHNAME', 'pgstatindex'
LANGUAGE C STRICT; LANGUAGE C STRICT;
-- CREATE OR REPLACE FUNCTION pg_relpages(IN relname text)
-- pg_relpages() RETURNS BIGINT
--
CREATE OR REPLACE FUNCTION pg_relpages(text)
RETURNS int
AS 'MODULE_PATHNAME', 'pg_relpages' AS 'MODULE_PATHNAME', 'pg_relpages'
LANGUAGE C STRICT; LANGUAGE C STRICT;
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgstattuple.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/pgstattuple.sgml,v 1.4 2008/03/21 03:23:30 tgl Exp $ -->
<sect1 id="pgstattuple"> <sect1 id="pgstattuple">
<title>pgstattuple</title> <title>pgstattuple</title>
...@@ -190,37 +190,37 @@ leaf_fragmentation | 0 ...@@ -190,37 +190,37 @@ leaf_fragmentation | 0
<row> <row>
<entry><structfield>index_size</structfield></entry> <entry><structfield>index_size</structfield></entry>
<entry><type>integer</type></entry> <entry><type>bigint</type></entry>
<entry>Total number of pages in index</entry> <entry>Total number of pages in index</entry>
</row> </row>
<row> <row>
<entry><structfield>root_block_no</structfield></entry> <entry><structfield>root_block_no</structfield></entry>
<entry><type>integer</type></entry> <entry><type>bigint</type></entry>
<entry>Location of root block</entry> <entry>Location of root block</entry>
</row> </row>
<row> <row>
<entry><structfield>internal_pages</structfield></entry> <entry><structfield>internal_pages</structfield></entry>
<entry><type>integer</type></entry> <entry><type>bigint</type></entry>
<entry>Number of <quote>internal</> (upper-level) pages</entry> <entry>Number of <quote>internal</> (upper-level) pages</entry>
</row> </row>
<row> <row>
<entry><structfield>leaf_pages</structfield></entry> <entry><structfield>leaf_pages</structfield></entry>
<entry><type>integer</type></entry> <entry><type>bigint</type></entry>
<entry>Number of leaf pages</entry> <entry>Number of leaf pages</entry>
</row> </row>
<row> <row>
<entry><structfield>empty_pages</structfield></entry> <entry><structfield>empty_pages</structfield></entry>
<entry><type>integer</type></entry> <entry><type>bigint</type></entry>
<entry>Number of empty pages</entry> <entry>Number of empty pages</entry>
</row> </row>
<row> <row>
<entry><structfield>deleted_pages</structfield></entry> <entry><structfield>deleted_pages</structfield></entry>
<entry><type>integer</type></entry> <entry><type>bigint</type></entry>
<entry>Number of deleted pages</entry> <entry>Number of deleted pages</entry>
</row> </row>
...@@ -250,7 +250,7 @@ leaf_fragmentation | 0 ...@@ -250,7 +250,7 @@ leaf_fragmentation | 0
<varlistentry> <varlistentry>
<term> <term>
<function>pg_relpages(text) returns integer</> <function>pg_relpages(text) returns bigint</>
</term> </term>
<listitem> <listitem>
...@@ -264,10 +264,10 @@ leaf_fragmentation | 0 ...@@ -264,10 +264,10 @@ leaf_fragmentation | 0
</sect2> </sect2>
<sect2> <sect2>
<title>Author</title> <title>Authors</title>
<para> <para>
Tatsuo Ishii Tatsuo Ishii and Satoshi Nagayasu
</para> </para>
</sect2> </sect2>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment