Adjust pgstatindex() to give correct answers for indexes larger than
authorTom Lane
Fri, 21 Mar 2008 03:23:30 +0000 (03:23 +0000)
committerTom Lane
Fri, 21 Mar 2008 03:23:30 +0000 (03:23 +0000)
2^31 blocks.  Also fix pg_relpages() for the same case.
Tatsuhito Kasahara

contrib/pgstattuple/pgstatindex.c
contrib/pgstattuple/pgstattuple.sql.in
doc/src/sgml/pgstattuple.sgml

index 3cd31478956f2c6bd5e353f085c60b1d3f0faacb..08200fafaebd7e2c4ef9120632bd7709f1392791 100644 (file)
@@ -59,19 +59,19 @@ PG_FUNCTION_INFO_V1(pg_relpages);
 typedef struct BTIndexStat
 {
    uint32      version;
-   BlockNumber root_blkno;
    uint32      level;
+   BlockNumber root_blkno;
 
-   uint32      root_pages;
-   uint32      internal_pages;
-   uint32      leaf_pages;
-   uint32      empty_pages;
-   uint32      deleted_pages;
+   uint64      root_pages;
+   uint64      internal_pages;
+   uint64      leaf_pages;
+   uint64      empty_pages;
+   uint64      deleted_pages;
 
-   uint32      max_avail;
-   uint32      free_space;
+   uint64      max_avail;
+   uint64      free_space;
 
-   uint32      fragments;
+   uint64      fragments;
 }  BTIndexStat;
 
 /* ------------------------------------------------------
@@ -87,8 +87,8 @@ pgstatindex(PG_FUNCTION_ARGS)
    Relation    rel;
    RangeVar   *relrv;
    Datum       result;
-   uint32      nblocks;
-   uint32      blkno;
+   BlockNumber nblocks;
+   BlockNumber blkno;
    BTIndexStat indexStat;
 
    if (!superuser())
@@ -112,30 +112,29 @@ pgstatindex(PG_FUNCTION_ARGS)
        BTMetaPageData *metad = BTPageGetMeta(page);
 
        indexStat.version = metad->btm_version;
-       indexStat.root_blkno = metad->btm_root;
        indexStat.level = metad->btm_level;
+       indexStat.root_blkno = metad->btm_root;
 
        ReleaseBuffer(buffer);
    }
 
-   nblocks = RelationGetNumberOfBlocks(rel);
-
-   /* -- init stat -- */
-   indexStat.fragments = 0;
-
+   /* -- init counters -- */
    indexStat.root_pages = 0;
-   indexStat.leaf_pages = 0;
    indexStat.internal_pages = 0;
+   indexStat.leaf_pages = 0;
    indexStat.empty_pages = 0;
    indexStat.deleted_pages = 0;
 
    indexStat.max_avail = 0;
    indexStat.free_space = 0;
 
-   /*-----------------------
-    * Scan all blocks
-    *-----------------------
+   indexStat.fragments = 0;
+
+   /*
+    * Scan all blocks except the metapage
     */
+   nblocks = RelationGetNumberOfBlocks(rel);
+
    for (blkno = 1; blkno < nblocks; blkno++)
    {
        Buffer      buffer;
@@ -151,13 +150,7 @@ pgstatindex(PG_FUNCTION_ARGS)
 
        /* Determine page type, and update totals */
 
-       if (P_ISDELETED(opaque))
-           indexStat.deleted_pages++;
-
-       else if (P_IGNORE(opaque))
-           indexStat.empty_pages++;
-
-       else if (P_ISLEAF(opaque))
+       if (P_ISLEAF(opaque))
        {
            int         max_avail;
 
@@ -174,9 +167,12 @@ pgstatindex(PG_FUNCTION_ARGS)
            if (opaque->btpo_next != P_NONE && opaque->btpo_next < blkno)
                indexStat.fragments++;
        }
+       else if (P_ISDELETED(opaque))
+           indexStat.deleted_pages++;
+       else if (P_IGNORE(opaque))
+           indexStat.empty_pages++;
        else if (P_ISROOT(opaque))
            indexStat.root_pages++;
-
        else
            indexStat.internal_pages++;
 
@@ -207,25 +203,26 @@ pgstatindex(PG_FUNCTION_ARGS)
        values[j] = palloc(32);
        snprintf(values[j++], 32, "%d", indexStat.level);
        values[j] = palloc(32);
-       snprintf(values[j++], 32, "%d", (indexStat.root_pages +
-                                        indexStat.leaf_pages +
-                                        indexStat.internal_pages +
-                                        indexStat.deleted_pages +
-                                        indexStat.empty_pages) * BLCKSZ);
+       snprintf(values[j++], 32, INT64_FORMAT,
+                (indexStat.root_pages +
+                 indexStat.leaf_pages +
+                 indexStat.internal_pages +
+                 indexStat.deleted_pages +
+                 indexStat.empty_pages) * BLCKSZ);
        values[j] = palloc(32);
-       snprintf(values[j++], 32, "%d", indexStat.root_blkno);
+       snprintf(values[j++], 32, "%u", indexStat.root_blkno);
        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);
-       snprintf(values[j++], 32, "%d", indexStat.leaf_pages);
+       snprintf(values[j++], 32, INT64_FORMAT, indexStat.leaf_pages);
        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);
-       snprintf(values[j++], 32, "%d", indexStat.deleted_pages);
+       snprintf(values[j++], 32, INT64_FORMAT, indexStat.deleted_pages);
        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);
-       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),
                                       values);
@@ -249,9 +246,9 @@ Datum
 pg_relpages(PG_FUNCTION_ARGS)
 {
    text       *relname = PG_GETARG_TEXT_P(0);
+   int64       relpages;
    Relation    rel;
    RangeVar   *relrv;
-   int4        relpages;
 
    if (!superuser())
        ereport(ERROR,
@@ -265,5 +262,5 @@ pg_relpages(PG_FUNCTION_ARGS)
 
    relation_close(rel, AccessShareLock);
 
-   PG_RETURN_INT32(relpages);
+   PG_RETURN_INT64(relpages);
 }
index 702e3fd2032e590e4c979f443ae79dd15622fa55..0d18f19dd00b30207e88fcd2dcb74ef6e17b774e 100644 (file)
@@ -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.
 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 tuple_count BIGINT,        -- number of live tuples
     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_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_percent FLOAT       -- free space in %
+    OUT free_percent FLOAT8)       -- free space in %
 AS 'MODULE_PATHNAME', 'pgstattuple'
 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 tuple_count BIGINT,        -- number of live tuples
     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_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_percent FLOAT       -- free space in %
+    OUT free_percent FLOAT8)       -- free space in %
 AS 'MODULE_PATHNAME', 'pgstattuplebyid'
 LANGUAGE C STRICT;
 
---
--- pgstatindex
---
 CREATE OR REPLACE FUNCTION pgstatindex(IN relname text,
-    OUT version int4,
-    OUT tree_level int4,
-    OUT index_size int4,
-    OUT root_block_no int4,
-    OUT internal_pages int4,
-    OUT leaf_pages int4,
-    OUT empty_pages int4,
-    OUT deleted_pages int4,
-    OUT avg_leaf_density float8,
-    OUT leaf_fragmentation float8)
+    OUT version INT,
+    OUT tree_level INT,
+    OUT index_size BIGINT,
+    OUT root_block_no BIGINT,
+    OUT internal_pages BIGINT,
+    OUT leaf_pages BIGINT,
+    OUT empty_pages BIGINT,
+    OUT deleted_pages BIGINT,
+    OUT avg_leaf_density FLOAT8,
+    OUT leaf_fragmentation FLOAT8)
 AS 'MODULE_PATHNAME', 'pgstatindex'
 LANGUAGE C STRICT;
 
---
--- pg_relpages()
---
-CREATE OR REPLACE FUNCTION pg_relpages(text)
-RETURNS int
+CREATE OR REPLACE FUNCTION pg_relpages(IN relname text)
+RETURNS BIGINT
 AS 'MODULE_PATHNAME', 'pg_relpages'
 LANGUAGE C STRICT;
index ad52dcd44205477eb5b8a455592203fc2d0ba6e3..f3a74181cf3c9b8027c7e0cd2c3e5e40b4112927 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  pgstattuple
@@ -190,37 +190,37 @@ leaf_fragmentation | 0
 
        
         index_size
-        integer
+        bigint
         Total number of pages in index
        
 
        
         root_block_no
-        integer
+        bigint
         Location of root block
        
 
        
         internal_pages
-        integer
+        bigint
         Number of internal (upper-level) pages
        
 
        
         leaf_pages
-        integer
+        bigint
         Number of leaf pages
        
 
        
         empty_pages
-        integer
+        bigint
         Number of empty pages
        
 
        
         deleted_pages
-        integer
+        bigint
         Number of deleted pages
        
 
@@ -250,7 +250,7 @@ leaf_fragmentation | 0
 
    
     
-     pg_relpages(text) returns integer
+     pg_relpages(text) returns bigint
     
 
     
@@ -264,10 +264,10 @@ leaf_fragmentation | 0
  
 
  
-  Author
+  Author<span class="marked">s</span>
 
   
-   Tatsuo Ishii
+   Tatsuo Ishii and Satoshi Nagayasu