Hi. In pgstatindex.c and pgstattuple.sql, some variables are defined with int type. So when we try to get informations about a large index by using pgstatindex, we get strange value of size and density. Because the values exceed int-max. # Like following output. I used pgstatindex just after data load. So "density" is should be nearly 90.
test=# SELECT * FROM pgstatindex('large_index'); -[ RECORD 1 ]------+------------ version | 2 tree_level | 4 index_size | -1349410816 ★ root_block_no | 119666 internal_pages | 28936 leaf_pages | 1379204 empty_pages | 0 deleted_pages | 0 avg_leaf_density | 60.33 ★ leaf_fragmentation | 0 I think that max_avail and free_space should be uint64. And the output format for index_size should be "%lld" (INT64_FORMAT). I made the patch and tryed it. (And it seemed OK.) test=# SELECT * FROM pgstatindex('large_index'); -[ RECORD 1 ]------+------------ version | 2 tree_level | 4 index_size | 11535491072 root_block_no | 119666 internal_pages | 28936 leaf_pages | 1379204 empty_pages | 0 deleted_pages | 0 avg_leaf_density | 90.64 leaf_fragmentation | 0 I also fix *_pages variables just in case. Please confirm this. Best regards. -- NTT OSS Center Tatsuhito Kasahara kasahara.tatsuhito _at_ oss.ntt.co.jp
diff -crN postgresql-8.3.0.org/contrib/pgstattuple/pgstatindex.c postgresql-8.3.0/contrib/pgstattuple/pgstatindex.c *** postgresql-8.3.0.org/contrib/pgstattuple/pgstatindex.c 2007-11-16 06:14:31.000000000 +0900 --- postgresql-8.3.0/contrib/pgstattuple/pgstatindex.c 2008-02-21 22:34:40.000000000 +0900 *************** *** 63,77 **** uint32 level; uint32 root_pages; ! uint32 internal_pages; ! uint32 leaf_pages; ! uint32 empty_pages; ! uint32 deleted_pages; ! uint32 max_avail; ! uint32 free_space; ! uint32 fragments; } BTIndexStat; /* ------------------------------------------------------ --- 63,77 ---- uint32 level; uint32 root_pages; ! uint64 internal_pages; ! uint64 leaf_pages; ! uint64 empty_pages; ! uint64 deleted_pages; ! uint64 max_avail; ! uint64 free_space; ! uint64 fragments; } BTIndexStat; /* ------------------------------------------------------ *************** *** 87,94 **** Relation rel; RangeVar *relrv; Datum result; ! uint32 nblocks; ! uint32 blkno; BTIndexStat indexStat; if (!superuser()) --- 87,94 ---- Relation rel; RangeVar *relrv; Datum result; ! BlockNumber nblocks; ! BlockNumber blkno; BTIndexStat indexStat; if (!superuser()) *************** *** 207,213 **** 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 + --- 207,213 ---- values[j] = palloc(32); snprintf(values[j++], 32, "%d", indexStat.level); values[j] = palloc(32); ! snprintf(values[j++], 32, INT64_FORMAT, (indexStat.root_pages + indexStat.leaf_pages + indexStat.internal_pages + indexStat.deleted_pages + *************** *** 215,231 **** values[j] = palloc(32); snprintf(values[j++], 32, "%d", indexStat.root_blkno); values[j] = palloc(32); ! snprintf(values[j++], 32, "%d", indexStat.internal_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, "%d", indexStat.leaf_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, "%d", indexStat.empty_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, "%d", indexStat.deleted_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, "%.2f", 100.0 - (float) indexStat.free_space / (float) indexStat.max_avail * 100.0); values[j] = palloc(32); ! snprintf(values[j++], 32, "%.2f", (float) indexStat.fragments / (float) indexStat.leaf_pages * 100.0); tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), values); --- 215,231 ---- values[j] = palloc(32); snprintf(values[j++], 32, "%d", indexStat.root_blkno); values[j] = palloc(32); ! snprintf(values[j++], 32, INT64_FORMAT, indexStat.internal_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, INT64_FORMAT, indexStat.leaf_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, INT64_FORMAT, indexStat.empty_pages); values[j] = palloc(32); ! snprintf(values[j++], 32, INT64_FORMAT, indexStat.deleted_pages); values[j] = palloc(32); ! 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", (double) indexStat.fragments / (double) indexStat.leaf_pages * 100.0); tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), values); diff -crN postgresql-8.3.0.org/contrib/pgstattuple/pgstattuple.sql.in postgresql-8.3.0/contrib/pgstattuple/pgstattuple.sql.in *** postgresql-8.3.0.org/contrib/pgstattuple/pgstattuple.sql.in 2007-11-13 13:24:28.000000000 +0900 --- postgresql-8.3.0/contrib/pgstattuple/pgstattuple.sql.in 2008-02-21 21:33:02.000000000 +0900 *************** *** 33,48 **** -- 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) AS 'MODULE_PATHNAME', 'pgstatindex' LANGUAGE C STRICT; --- 33,48 ---- -- pgstatindex -- CREATE OR REPLACE FUNCTION pgstatindex(IN relname text, ! OUT version INT, ! OUT tree_level INT, ! OUT index_size BIGINT, ! OUT root_block_no INT, ! 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;
---------------------------(end of broadcast)--------------------------- TIP 2: Don't 'kill -9' the postmaster