Hola Marcos, husmeando en mi lote de consultas al catálogo, hice un Mega-MIX y logré algo aproximado a lo que necesitas, le puedes hacer tus ajustes en dependencia de los tipos de datos que tengas: La consulta te devuelve una fila con la tabla y los bytes aproximado de cada tupla de esa tabla para que multiplicando esos byte por las cantidad de tuplas te daría un valor del tamaño de la tabla +-, jeje (tiene algunos comentarios pera que la puedas ajustar):

with tipos as (SELECT SCHEMANAME||'.'||relname as tabla,attname,t.typname,attlen
    FROM pg_class join pg_attribute on (pg_attribute.attrelid=pg_class.oid)
    join pg_tables on (pg_class.relname=pg_tables.tablename)
    join pg_type t on ( pg_attribute.atttypid = t.oid)
WHERE SCHEMANAME <> 'pg_catalog' and SCHEMANAME <> 'information_schema'
    --AND attnum > 0
    ORDER BY attnum)

select tabla, sum(
case when attlen=-1 and ins.character_maximum_length<>0 then pg_column_size(generar_texto(ins.character_maximum_length))
--hice el tratamiendo del algunos,  valora si te faltan
when attlen=-1 and ins.character_maximum_length is null then pg_column_size(generar_texto(10000)::character varying)-- para cuando es character varying y no se sabemos la precisión when typname::text='numeric' and ins.character_maximum_length is not null then pg_column_size(generar_texto_numero(ins.numeric_precision-ins.numeric_scale)||'.'||generar_texto_numero(ins.numeric_scale)::numeric) when typname::text='numeric' and ins.character_maximum_length is null then pg_column_size('99999999999999999999.99999999'::numeric) --para cuando no sabemos la precisión de numeric when typname::text='text' then pg_column_size(generar_texto(10000))-- se valora texto de 10000 caracteres when typname::text='bytea' then 1000000 --este valor lo puse haciendo un aproximado de 1000000, ajustalo a lo que consideres que se pueda llevar un bytea en tu BD -- aqui puedes poner los tipos de datos que crees que puedes tener en tu BD, estoy pensado en los ARRAY por ejemplo
else
attlen
end)+26 as longitud --se le suma 26 byte por ser el tamaño de las columnas especiales xmin, xmax, etc...

from tipos , information_schema.columns ins where (tipos.tabla=ins.table_schema||'.'||ins.table_name) and
attname=ins.column_name group by 1

Para que funcione debes tener creadas dos funciones que te pongo a continuación, las utilizo de apoyo:

-- Function: generar_texto(integer)

-- DROP FUNCTION generar_texto(integer);

CREATE OR REPLACE FUNCTION generar_texto(integer)
  RETURNS character varying AS
$BODY$
DECLARE
  chars text[] :='{
                    0,1,2,3,4,5,6,7,8,9,
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
                  }';
BEGIN
  RETURN (
        SELECT
            array_to_string(
               ARRAY(
                     SELECT
                          chars[1+random()*(array_length(chars, 1)-1)]
                     FROM
                          generate_series(1,$1)
               ), ''
            )
         );
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION generar_texto(integer)
  OWNER TO postgres;


-- Function: generar_texto_numero(integer)

-- DROP FUNCTION generar_texto_numero(integer);

CREATE OR REPLACE FUNCTION generar_texto_numero(integer)
  RETURNS character varying AS
$BODY$
DECLARE
  chars text[] :='{
                    1,2,3,4,5,6,7,8,9
                      }';
BEGIN
  RETURN (
        SELECT
            array_to_string(
               ARRAY(
                     SELECT
                          chars[1+random()*(array_length(chars, 1)-1)]
                     FROM
                          generate_series(1,$1)
               ), ''
            )
         );
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION generar_texto_numero(integer)
  OWNER TO postgres;



Saludos y espero que te ayude compadre.
Anthony


PD: si quieres un poco más de detalles de las columnas puedes ejecutar esta, donde no está el SUM():

with tipos as (SELECT SCHEMANAME||'.'||relname as tabla,attname,t.typname,attlen
    FROM pg_class join pg_attribute on (pg_attribute.attrelid=pg_class.oid)
    join pg_tables on (pg_class.relname=pg_tables.tablename)
    join pg_type t on ( pg_attribute.atttypid = t.oid)
WHERE SCHEMANAME <> 'pg_catalog' and SCHEMANAME <> 'information_schema'
    --AND attnum > 0
    ORDER BY attnum)

select tabla,attname,typname, attlen,
case when attlen=-1 and ins.character_maximum_length<>0 then pg_column_size(generar_texto(ins.character_maximum_length)) when attlen=-1 and ins.character_maximum_length is null then pg_column_size(generar_texto(10000)::character varying)-- para cuando es character varying y no se sabemos la precision when typname::text='numeric' and ins.character_maximum_length is not null then pg_column_size(generar_texto_numero(ins.numeric_precision-ins.numeric_scale)||'.'||generar_texto_numero(ins.numeric_scale)::numeric) when typname::text='numeric' and ins.character_maximum_length is null then pg_column_size('99999999999999999999.99999999'::numeric) --para cuando no sabemos la precision de numeric when typname::text='text' then pg_column_size(generar_texto(10000))--valorar texto de 10000 caracteres
else
attlen
end as longitud

from tipos , information_schema.columns ins where (tipos.tabla=ins.table_schema||'.'||ins.table_name) and
attname=ins.column_name










El 2/19/2015 a las 10:31 AM, Marcos Ortiz escribió:
Saludos a toda la lista.
Estamos en el desarrollo de una nueva aplicación con PostgreSQL 9.4 y necesitamos hacer la estimación del crecimiento de la base de datos. La vía tradicional es recorrer cada uno de los campos de cada tabla, ver su tipo de dato y ver cuánto espacio ocupa cada uno, luego ver con todos los campos cuánto se lleva la tupla, y luego repetir este proceso por cada una de las tablas. Pero pienso que debe haber alguna utilidad o herramienta moderna para realizar esto de forma automatizada y rápida. ¿Conocen de alguna herramienta enfocada en este problema?




Responder a