mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Adjust pgstatindex() to give correct answers for indexes larger than
2^31 blocks. Also fix pg_relpages() for the same case. Tatsuhito Kasahara
This commit is contained in:
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
|
|
||||||
relation_close(rel, AccessShareLock);
|
relation_close(rel, AccessShareLock);
|
||||||
|
|
||||||
PG_RETURN_INT32(relpages);
|
PG_RETURN_INT64(relpages);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $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
|
|||||||
|
|
||||||
<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
|
|||||||
|
|
||||||
<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
|
|||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Author</title>
|
<title>Authors</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Tatsuo Ishii
|
Tatsuo Ishii and Satoshi Nagayasu
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user