Получить размер большого объекта в запросе PostgreSQL?

Я хотел бы получить размер байта blob.

Я использую Postgresql и хотел бы получить размер с помощью SQL-запроса. Что-то вроде этого:

SELECT sizeof(field) FROM table;

Возможно ли это в Postgresql?

Обновление: я прочитал руководство postgresql и не смог найти подходящую функцию для вычисления размера файла. Кроме того, blob хранится как большой объект.

Ответ 1

Не то, что я использовал большие объекты, но смотрю на документы: http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

Я думаю, вам нужно использовать ту же технику, что и некоторые API-интерфейсы файловой системы: ищите до конца, а затем укажите позицию. PostgreSQL имеет SQL-функции, которые, как представляется, обертывают внутренние функции C. Я не мог найти много документации, но это сработало:

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

Тестирование:

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

Похоже, что функции LO предназначены для использования в основном через клиента или через низкоуровневое серверное программирование, но по крайней мере они предоставили для него некоторые видимые для SQL функции, что делает возможным это выше. Я сделал запрос для SELECT relname FROM pg_proc where relname LIKE 'lo%', чтобы начать работу. Смутные воспоминания о программировании на С и немного исследований для значений режима x'40000'::int и SEEK_END = 2 были необходимы для остальных!

Ответ 2

Вы можете изменить приложение, чтобы сохранить размер при создании большого объекта. В противном случае вы можете использовать запрос, например:

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

Вы также можете использовать функции API большого объекта, как это было предложено в предыдущем сообщении, они работают нормально, но на порядок медленнее, чем предложенный выше метод выбора.

Ответ 3

select pg_column_size(lo_get(lo_oid)) from table;

Дает размер в байтах.

Если вам нужна красивая печать:

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

Ответ 4

Попробуйте length() или octet_length()

Ответ 5

Это мое решение:

select
lo.loid,
pg_size_pretty(sum(octet_length(lo.data)))
from pg_largeobject lo
where lo.loid in (select pg_largeobject.loid from pg_largeobject)
group by lo.loid;