2012-04-16 22 views
9

Chciałbym uzyskać rozmiar bajtów obiektu typu blob.Uzyskaj rozmiar dużego obiektu w zapytaniu PostgreSQL?

Używam PostgreSQL i chciałbym uzyskać rozmiar przy użyciu zapytania SQL. Coś takiego:

SELECT sizeof(field) FROM table; 

Czy to możliwe w Postgresql?

Aktualizacja: zapoznałem się z podręcznikiem PostgreSQL i nie mogłem znaleźć odpowiedniej funkcji do obliczenia rozmiaru pliku. Ponadto obiekt typu blob jest przechowywany jako duży obiekt.

+0

Proszę przed wysłaniem takie pytanie przeczytać instrukcję: http://www.postgresql.org/docs/current/static/functions.html –

+2

Zdefiniuj „Dane blob ". A kolumna bytea "? Lub duży obiekt przechowywany w 'pg_largeobject'? Pokaż definicję stołu. –

+0

Duplikat [Uzyskanie rozmiaru lobject w PostgreSQL] (http://stackoverflow.com/questions/9248738/obtaining-the-size-of-lobject-in-postgressql)? –

Odpowiedz

12

Nie, że użyłem dużych obiektów, ale patrząc na docs: http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

myślę, trzeba użyć tej samej techniki, ponieważ niektóre interfejsy API systemu plików wymaga: dążyć do koniec, a następnie powiedz pozycję. PostgreSQL ma funkcje SQL, które wydają się owijać wewnętrzne funkcje C. Nie mogłem znaleźć wiele dokumentacji, ale to działało:

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

testowanie go:

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

Wydaje się, że funkcjonalność LO jest przeznaczony do stosowania głównie przez klienta lub serwera poprzez programowanie niskopoziomowe , ale przynajmniej dostarczyły dla niego pewne widoczne funkcje SQL, co umożliwia powyższe. Zrobiłem zapytanie do SELECT relname FROM pg_proc where relname LIKE 'lo%', aby zacząć. Nieliczne wspomnienia programowania C i trochę badań dla wartości trybu x'40000'::int i SEEK_END = 2 były potrzebne dla reszty!

3

Spróbuj length() lub octet_length()

10

Możesz zmienić swoją aplikację, aby zapisać rozmiar podczas tworzenia dużego obiektu. W przeciwnym wypadku można użyć kwerendy, takie jak:

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

Można użyć także duże funkcje obiektu API, jak zasugerowano w poprzednim poście, że działa ok, ale są o rząd wielkości mniejszą niż metody Select zasugerowano powyżej .

+0

To jest najczystsze rozwiązanie. Dzięki – MarekM

+1

Niestety, katalog 'pg_largeobject' nie jest już publicznie dostępny od 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; 

Podaje rozmiar w bajtach.

Jeśli chcesz ładny druk:

select pg_size_pretty(pg_column_size(lo_get(lo_oid))::numeric) from table; 
Powiązane problemy