2012-04-16 6 views
9

Ich möchte die Byte-Größe eines Blobs erhalten.Get Größe des großen Objekts in PostgreSQL-Abfrage?

Ich verwende Postgresql und möchte die Größe mit einer SQL-Abfrage erhalten. Etwas wie dieses:

SELECT sizeof(field) FROM table; 

Ist das in Postgresql möglich?

Update: Ich habe das Postgresql Handbuch gelesen und konnte keine geeignete Funktion finden, um die Dateigröße zu berechnen. Außerdem wird der Blob als großes Objekt gespeichert.

+0

Bitte lesen Sie das Handbuch, bevor eine solche Frage Posting: http://www.postgresql.org/docs/current/static/functions.html –

+2

definieren „Blob-Daten ". Eine Byteasäule? Oder ein großes Objekt in 'pg_largeobject' gespeichert? Zeigen Sie Ihre Tabellendefinition an. –

+0

Duplizieren von [Erhalten der Größe des LOB-Objekts in PostgresSQL] (http://StackOverflow.com/Questions/9248738/Berechtigung-der-Size-Ob-Lobject-in-Postgressql)? –

Antwort

12

Nicht, dass ich große Objekte verwendet habe, aber bei der Dokumentation suchen: http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

Ich glaube, Sie die gleiche Technik verwenden müssen, da einige Dateisystem-APIs erfordern: versuchen, das Ende, dann sagen Sie die Position. PostgreSQL verfügt über SQL-Funktionen, die die internen C-Funktionen zu umbrechen scheinen. Ich konnte nicht viel Dokumentation finden, aber das funktionierte:

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; 
$$; 

Testing es:

-- 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); 

Es ist die LO-Funktionalität scheint ist so konzipiert, vor allem durch den Kunden oder durch Low-Level-Server-Programmierung verwendet werden , aber zumindest haben sie einige SQL-sichtbare Funktionen für sie zur Verfügung gestellt, die das obige möglich machen. Ich habe eine Abfrage für SELECT relname FROM pg_proc where relname LIKE 'lo%' gemacht, um mich selbst zu beginnen. Vage Erinnerungen an C-Programmierung und ein wenig Forschung für die Mode x'40000'::int und SEEK_END = 2 Wert wurden für den Rest benötigt!

3

Versuchen length() oder octet_length()

10

Sie könnten Ihre Anwendung ändern, um die Größe beim Erstellen des großen Objekts zu speichern. Ansonsten können Sie eine Abfrage verwenden, wie zum Beispiel:

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

Sie auch Funktionen der großen Objekt-API verwenden können, wie in einem frühen Post vorgeschlagen, sie in Ordnung arbeiten, sind aber um eine Größenordnung langsamer als die select-Methode oben vorgeschlagen .

+0

Dies ist die sauberste Lösung. Danke – MarekM

+1

Leider ist der 'pg_largeobject' Katalog seit PostgreSQL 9.0 nicht mehr öffentlich zugänglich: https://www.postgresql.org/docs/current/static/catalog-pg-largeobject.html. – ochedru

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

Gibt Ihnen die Größe in Bytes.

Wenn Sie ziemlich Druck wollen:

select pg_size_pretty(pg_column_size(lo_get(lo_oid))::numeric) from table; 
Verwandte Themen