Index: README.dbsize
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/dbsize/README.dbsize,v
retrieving revision 1.4
diff -C1 -r1.4 README.dbsize
*** README.dbsize	28 Sep 2004 19:35:43 -0000	1.4
--- README.dbsize	6 Feb 2005 15:06:19 -0000
***************
*** 1,3 ****
! This module contains several functions that report the size of a given
! database object:
  
--- 1,3 ----
! This module contains several functions that report the on-disk size of a 
! given database object in bytes:
  
***************
*** 5,6 ****
--- 5,8 ----
  	int8 relation_size(text)
+ 	int8 indexes_size(text)
+ 	int8 aggregate_relation_size(text)
  
***************
*** 12,14 ****
  
! The first two functions:
  
--- 14,20 ----
  
! 	setof record relation_size_components(text)
! 
! The first four functions take the name of the object (possibly 
! schema-qualified for the latter three) and returns the size of the
! on-disk files in bytes.
  
***************
*** 16,20 ****
  	SELECT relation_size('pg_class');
  
! take the name of the object (possibly schema-qualified, for relation_size),
! while these functions take object OIDs:
  	
--- 22,27 ----
  	SELECT relation_size('pg_class');
+ 	SELECT indexes_size('pg_class');
+ 	SELECT aggregate_relation_size('pg_class');
  
! These functions take object OIDs:
  	
***************
*** 24,49 ****
  
  Please note that relation_size and pg_relation_size report only the size of
! the selected relation itself; any subsidiary indexes or toast tables are not
! counted.  To obtain the total size of a table including all helper files
! you'd have to do something like:
! 
! SELECT *,
!     pg_size_pretty(tablesize+indexsize+toastsize+toastindexsize) AS totalsize
! FROM
! (SELECT pg_relation_size(cl.oid) AS tablesize,
!         COALESCE((SELECT SUM(pg_relation_size(indexrelid))::bigint
!                   FROM pg_index WHERE cl.oid=indrelid), 0) AS indexsize,
!         CASE WHEN reltoastrelid=0 THEN 0
!              ELSE pg_relation_size(reltoastrelid)
!         END AS toastsize,
!         CASE WHEN reltoastrelid=0 THEN 0
!              ELSE pg_relation_size((SELECT reltoastidxid FROM pg_class ct
!                                     WHERE ct.oid = cl.reltoastrelid))
!         END AS toastindexsize
!  FROM pg_class cl
!  WHERE relname = 'foo') ss;
! 
! This sample query utilizes the helper function pg_size_pretty(int8),
! which formats the number of bytes into a convenient string using KB, MB,
! GB.  It is also contained in this module.
  
--- 31,113 ----
  
+ The indexes_size() function returns the total size of the indices for a 
+ relation, including any toasted indices.
+ 
+ The aggregate_relation_size() function returns the total size of the relation,
+ all its indices, and any toasted data.  
+ 
  Please note that relation_size and pg_relation_size report only the size of
! the selected relation itself; any related indexes or toast tables are not
! counted.  To obtain the total size of a table including all indices and
! toasted data, use aggregate_relation_size().
! 
! The last function, relation_size_components(), returns a set of rows
! showing the sizes of the component relations constituting the input 
! relation.  
! 
! Examples
! ========
! 
! I've loaded the following table with a little less than 3 MB of data for 
! illustration:
! 
!     create table fat ( id serial, data varchar );
!     create index fat_uidx on fat (id);
!     create index fat_idx on fat (data);
! 
! You can retrieve a rowset containing constituent sizes as follows:
! 
! # SELECT relation_size_components('fat');
!               relation_size_components              
! ----------------------------------------------------
!  (2088960,65536,2891776,fat,r,59383,59383)
!  (32768,704512,737280,pg_toast_59383,t,59386,59386)
!  (0,32768,32768,pg_toast_59383_index,i,59388,59388)
!  (0,2039808,2039808,fat_idx,i,59389,59389)
!  (0,49152,49152,fat_uidx,i,59911,59911)
! (5 rows)
! 
! To see a more readable output of the rowset:
! 
!     SELECT * 
!     FROM relation_size_components('fat') AS (idxsize BIGINT, 
!                                              datasize BIGINT, 
!                                              totalsize BIGINT, 
!                                              relname NAME, 
!                                              kind "char", 
!                                              relid OID, 
!                                              node OID) 
!     ORDER BY totalsize;
! 
!  idxsize | datasize | totalsize |       relname        | kind | relid | node  
! ---------+----------+-----------+----------------------+------+-------+-------
!        0 |    32768 |     32768 | pg_toast_59383_index | i    | 59388 | 59388
!        0 |    49152 |     49152 | fat_uidx             | i    | 59911 | 59911
!    32768 |   704512 |    737280 | pg_toast_59383       | t    | 59386 | 59386
!        0 |  2039808 |   2039808 | fat_idx              | i    | 59389 | 59389
!  2088960 |    65536 |   2891776 | fat                  | r    | 59383 | 59383
! (5 rows)
! 
! To see the sum total size of a relation:
! 
! # select aggregate_relation_size('fat');
!  aggregate_relation_size 
! -------------------------
!                  2891776
! (1 row)
! 
! To see just the size of the uncompressed relation data:
! 
! # select relation_size('fat');
!  relation_size 
! ---------------
!          65536
! (1 row)
! 
! To see the size of all related indices:
! 
! # select indexes_size('fat');
!  indexes_size 
! --------------
!       2088960
! (1 row)
  
Index: dbsize.sql.in
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/dbsize/dbsize.sql.in,v
retrieving revision 1.4
diff -C1 -r1.4 dbsize.sql.in
*** dbsize.sql.in	28 Sep 2004 19:35:43 -0000	1.4
--- dbsize.sql.in	6 Feb 2005 15:06:19 -0000
***************
*** 23 ****
--- 23,132 ----
      LANGUAGE C STRICT;
+ 
+ CREATE FUNCTION aggregate_relation_size (text) RETURNS bigint AS '
+ SELECT pg_relation_size(r.oid)
+      + COALESCE(pg_relation_size(t.oid), 0)::bigint
+      + COALESCE(pg_relation_size(ti.oid), 0)::bigint
+      + COALESCE(SUM(pg_relation_size(i.indexrelid)), 0)::bigint
+      + COALESCE(SUM(pg_relation_size(it.oid)), 0)::bigint
+      + COALESCE(SUM(pg_relation_size(iti.oid)), 0)::bigint AS bytes
+ FROM pg_class r 
+      LEFT JOIN pg_class t   ON (r.reltoastrelid = t.oid) 
+      LEFT JOIN pg_class ti  ON (t.reltoastidxid = ti.oid) 
+      LEFT JOIN pg_index i   ON (r.oid = i.indrelid) 
+      LEFT JOIN pg_class ir  ON (ir.oid = i.indexrelid) 
+      LEFT JOIN pg_class it  ON (ir.reltoastrelid = it.oid) 
+      LEFT JOIN pg_class iti ON (it.reltoastidxid = iti.oid) 
+ WHERE r.relname = \$1 
+ GROUP BY r.oid, t.oid, ti.oid
+ ' LANGUAGE SQL;
+ 
+ CREATE FUNCTION indexes_size (text) RETURNS bigint 
+     AS '
+ SELECT COALESCE(SUM(pg_relation_size(ir.oid)), 0)::bigint
+      + COALESCE(SUM(pg_relation_size(it.oid)), 0)::bigint
+      + COALESCE(SUM(pg_relation_size(iti.oid)), 0)::bigint AS bytes
+ FROM pg_class r 
+      LEFT JOIN pg_index i   ON (r.oid = i.indrelid) 
+      LEFT JOIN pg_class ir  ON (ir.oid = i.indexrelid) 
+      LEFT JOIN pg_class it  ON (ir.reltoastrelid = it.oid) 
+      LEFT JOIN pg_class iti ON (it.reltoastidxid = iti.oid) 
+ WHERE r.relname = \$1 
+ ' LANGUAGE SQL;
+ 
+ CREATE FUNCTION relation_size_components (text) RETURNS SETOF RECORD
+     AS '
+ -- relation size
+ SELECT indexes_size(r.relname) AS indexes_size, 
+        relation_size(r.relname) AS data_size, 
+        aggregate_relation_size(r.relname) AS total_size, 
+        r.relname, r.relkind, r.oid AS relid, r.relfilenode 
+ FROM pg_class r 
+ WHERE r.relname = \$1 
+ 
+ UNION ALL 
+ 
+ -- relation toast size
+ SELECT indexes_size(toast.relname) AS indexes_size, 
+        relation_size(''pg_toast.''||toast.relname) AS data_size, 
+        aggregate_relation_size(toast.relname) AS total_size, 
+        toast.relname, toast.relkind, toast.oid AS relid, toast.relfilenode 
+ FROM pg_class r, pg_class toast
+ WHERE r.reltoastrelid = toast.oid 
+   AND r.relname = \$1 
+ 
+ UNION ALL 
+ 
+ -- relation toast index size
+ SELECT indexes_size(toastidxr.relname) AS indexes_size, 
+        relation_size(''pg_toast.''||toastidxr.relname) AS data_size, 
+        aggregate_relation_size(toastidxr.relname) AS total_size, 
+        toastidxr.relname, toastidxr.relkind, 
+        toastidxr.oid AS relid, toastidxr.relfilenode 
+ FROM pg_class r, pg_index toastidx, pg_class toastidxr
+ WHERE r.relname = \$1
+   AND r.reltoastrelid = toastidx.indrelid 
+   AND toastidx.indexrelid = toastidxr.oid 
+ 
+ UNION ALL 
+ 
+ -- relation indices size
+ SELECT indexes_size(idxr.relname) AS indexes_size, 
+        relation_size(idxr.relname) AS data_size, 
+        aggregate_relation_size(idxr.relname) AS total_size, 
+        idxr.relname, idxr.relkind, idxr.oid AS relid, idxr.relfilenode 
+ FROM pg_class r, pg_class idxr, pg_index idx 
+ WHERE r.relname = \$1
+   AND r.oid = idx.indrelid
+   AND idx.indexrelid = idxr.oid 
+ 
+ UNION ALL 
+ 
+ -- relation indices toast size
+ SELECT indexes_size(idxtoastr.relname) AS indexes_size, 
+        relation_size(''pg_toast.''||idxtoastr.relname) AS data_size, 
+        aggregate_relation_size(idxtoastr.relname) AS total_size, 
+        idxtoastr.relname, idxtoastr.relkind, idxtoastr.oid AS relid, 
+        idxtoastr.relfilenode 
+ FROM pg_class r, pg_class idxr, pg_index idx, pg_class idxtoastr
+ WHERE r.relname = \$1
+   AND r.oid = idx.indrelid
+   AND idx.indexrelid = idxr.oid 
+   AND idxr.reltoastrelid = idxtoastr.oid 
+ 
+ UNION ALL 
+ 
+ -- relation indices toast index size
+ SELECT indexes_size(idxtoastidxr.relname) AS indexes_size, 
+        relation_size(''pg_toast.''||idxtoastidxr.relname) AS data_size, 
+        aggregate_relation_size(idxtoastidxr.relname) AS total_size, 
+        idxtoastidxr.relname, idxtoastidxr.relkind, 
+        idxtoastidxr.oid AS relid, idxtoastidxr.relfilenode 
+ FROM pg_class r, pg_class idxr, pg_index idx, pg_class idxtoast, 
+      pg_class idxtoastidxr
+ WHERE r.relname = \$1
+   AND r.oid = idx.indrelid
+   AND idx.indexrelid = idxr.oid 
+   AND idxr.reltoastrelid = idxtoast.oid 
+   AND idxtoast.reltoastrelid = idxtoastidxr.oid 
+ ' LANGUAGE SQL;
+ 
