2012-04-16 10 views
9

Me gustaría obtener el tamaño de bytes de un blob.¿Obtiene el tamaño del objeto grande en la consulta de PostgreSQL?

Estoy usando Postgresql y me gustaría obtener el tamaño mediante una consulta SQL. Algo como esto:

SELECT sizeof(field) FROM table; 

¿Es esto posible en Postgresql?

Actualización: He leído el manual postgresql y no he podido encontrar una función apropiada para calcular el tamaño del archivo. Además, el blob se almacena como un objeto grande.

+0

Por favor, lea el manual antes de publicar una pregunta tan: http://www.postgresql.org/docs/current/static/functions.html –

+2

Definir "datos blob ". Una columna de bytea'? ¿O un objeto grande almacenado en 'pg_largeobject'? Muestra la definición de tu tabla. –

+0

Duplicado de [Obtención del tamaño de lobject en PostgresSQL] (http://stackoverflow.com/questions/9248738/obtaining-the-size-of-lobject-in-postgressql)? –

Respuesta

12

No es que yo he usado objetos de gran tamaño, pero mirando a los documentos: http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

Yo creo que hay que utilizar la misma técnica que algunas API del sistema de archivos requieren: procurar al final, luego diga la posición. PostgreSQL tiene funciones SQL que parecen envolver las funciones C internas. No pude encontrar mucha documentación, pero esto trabajado:

CREATE OR REPLACE FUNCTION get_lo_size(oid) RETURNS bigint 
VOLATILE STRICT 
LANGUAGE 'plpgsql' 
AS $$ 
DECLARE 
    fd integer; 
    sz bigint; 
BEGIN 
    -- Open the LO; N.B. it needs to be in a transaction otherwise it will close immediately. 
    -- Luckily a function invocation makes its own transaction if necessary. 
    -- The mode x'40000'::int corresponds to the PostgreSQL LO mode INV_READ = 0x40000. 
    fd := lo_open($1, x'40000'::int); 
    -- Seek to the end. 2 = SEEK_END. 
    PERFORM lo_lseek(fd, 0, 2); 
    -- Fetch the current file position; since we're at the end, this is the size. 
    sz := lo_tell(fd); 
    -- Remember to close it, since the function may be called as part of a larger transaction. 
    PERFORM lo_close(fd); 
    -- Return the size. 
    RETURN sz; 
END; 
$$; 

probándola:

-- Make a new LO, returns an OID e.g. 1234567 
SELECT lo_create(0); 

-- Populate it with data somehow 
... 

-- Get the length. 
SELECT get_lo_size(1234567); 

Parece que la funcionalidad LO está diseñado para ser utilizado sobre todo a través del cliente o servidor a través de la programación de bajo nivel , pero al menos han proporcionado algunas funciones SQL visibles para él, lo que hace que lo anterior sea posible. Hice una consulta para SELECT relname FROM pg_proc where relname LIKE 'lo%' para comenzar. Se necesitaban vagos recuerdos de la programación C y un poco de investigación para el modo x'40000'::int y SEEK_END = 2 ¡valor para el resto!

3

Trate length() o octet_length()

10

Puede cambiar su aplicación para almacenar el tamaño cuando crea el objeto grande. De lo contrario, puede utilizar una consulta como:

select sum(length(lo.data)) from pg_largeobject lo 
where lo.loid=XXXXXX 

Puede utilizar también las grandes funciones de la API objeto, como se sugiere en un post anterior, trabajan bien, pero son un orden de magnitud más lento que el método de selección se sugirió anteriormente .

+0

Esta es la solución más limpia. Gracias – MarekM

+1

Desafortunadamente, el catálogo 'pg_largeobject' ya no es accesible al público desde PostgreSQL 9.0: https://www.postgresql.org/docs/current/static/catalog-pg-largeobject.html. – ochedru

4
select pg_column_size(lo_get(lo_oid)) from table; 

Te da el tamaño en bytes.

Si desea bastante impresión:

select pg_size_pretty(pg_column_size(lo_get(lo_oid))::numeric) from table; 
Cuestiones relacionadas